@letta-ai/letta-code 0.32.1 → 0.32.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/dist/agent-presets.js +25 -1
- package/dist/agent-presets.js.map +2 -2
- package/dist/channels-public.js +32 -2
- package/dist/channels-public.js.map +3 -3
- package/dist/channels-slack.js +100 -4
- package/dist/channels-slack.js.map +7 -6
- package/dist/gateway-core.js +125 -32
- package/dist/gateway-core.js.map +8 -7
- package/dist/mcp-client.js +2 -2
- package/dist/mcp-client.js.map +1 -1
- package/dist/memory-constraints.js +77 -1
- package/dist/memory-constraints.js.map +5 -4
- package/dist/types/agent/memory-git-hooks.d.ts +1 -1
- package/dist/types/agent/memory-git-hooks.d.ts.map +1 -1
- package/dist/types/agent/skills.d.ts.map +1 -1
- package/dist/types/agent/subagents/manager.d.ts.map +1 -1
- package/dist/types/backend/backend.d.ts +0 -1
- package/dist/types/backend/backend.d.ts.map +1 -1
- package/dist/types/backend/dev/fake-headless-backend.d.ts.map +1 -1
- package/dist/types/channels/gateway-core.d.ts +2 -0
- package/dist/types/channels/gateway-core.d.ts.map +1 -1
- package/dist/types/channels/gateway-sources.d.ts +6 -0
- package/dist/types/channels/gateway-sources.d.ts.map +1 -0
- package/dist/types/channels/message-channel-bindings.d.ts +39 -0
- package/dist/types/channels/message-channel-bindings.d.ts.map +1 -0
- package/dist/types/channels/message-channel-executor.d.ts +4 -0
- package/dist/types/channels/message-channel-executor.d.ts.map +1 -1
- package/dist/types/channels/message-channel-tool-definition.d.ts.map +1 -1
- package/dist/types/channels/message-channel-types.d.ts +3 -1
- package/dist/types/channels/message-channel-types.d.ts.map +1 -1
- package/dist/types/channels/plugin-types.d.ts +9 -1
- package/dist/types/channels/plugin-types.d.ts.map +1 -1
- package/dist/types/channels/progress-builder.d.ts +1 -1
- package/dist/types/channels/progress-builder.d.ts.map +1 -1
- package/dist/types/channels/progress-types.d.ts +28 -0
- package/dist/types/channels/progress-types.d.ts.map +1 -0
- package/dist/types/channels/slack/message-action-contract.d.ts +2 -0
- package/dist/types/channels/slack/message-action-contract.d.ts.map +1 -1
- package/dist/types/channels/slack/progress.d.ts.map +1 -1
- package/dist/types/channels/slack/status-controller.d.ts +2 -1
- package/dist/types/channels/slack/status-controller.d.ts.map +1 -1
- package/dist/types/channels/types.d.ts +6 -23
- package/dist/types/channels/types.d.ts.map +1 -1
- package/dist/types/cli/helpers/app-urls.d.ts +0 -4
- package/dist/types/cli/helpers/app-urls.d.ts.map +1 -1
- package/dist/types/cli/helpers/error-formatter.d.ts.map +1 -1
- package/dist/types/gateway-core.d.ts +1 -0
- package/dist/types/gateway-core.d.ts.map +1 -1
- package/dist/types/memory-constraints.d.ts +1 -0
- package/dist/types/memory-constraints.d.ts.map +1 -1
- package/dist/types/memory-frontmatter.d.ts +18 -0
- package/dist/types/memory-frontmatter.d.ts.map +1 -0
- package/dist/types/tools/letta-toolset.d.ts +10 -0
- package/dist/types/tools/letta-toolset.d.ts.map +1 -0
- package/dist/types/tools/toolset-options.d.ts +4 -0
- package/dist/types/tools/toolset-options.d.ts.map +1 -0
- package/dist/types/tools/toolset-types.d.ts +1 -2
- package/dist/types/tools/toolset-types.d.ts.map +1 -1
- package/dist/types/tools/toolset.d.ts.map +1 -1
- package/dist/types/types/protocol_v2.d.ts +3 -2
- package/dist/types/types/protocol_v2.d.ts.map +1 -1
- package/dist/types/types/toolset-protocol.d.ts +10 -0
- package/dist/types/types/toolset-protocol.d.ts.map +1 -0
- package/dist/types/websocket/listener/device-toolset-status.d.ts +6 -0
- package/dist/types/websocket/listener/device-toolset-status.d.ts.map +1 -0
- package/dist/types/websocket/listener/protocol-outbound.d.ts.map +1 -1
- package/letta.js +968 -1482
- package/package.json +2 -1
- package/scripts/source-file-size-baseline.json +6 -6
- package/skills/image-generation/SKILL.md +5 -4
- package/skills/self-configuration/SKILL.md +1 -1
- package/skills/working-across-computers/SKILL.md +88 -0
- package/skills/teleporting-between-environments/SKILL.md +0 -114
package/letta.js
CHANGED
|
@@ -66,6 +66,50 @@ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
|
66
66
|
var __promiseAll = (args) => Promise.all(args);
|
|
67
67
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
68
68
|
|
|
69
|
+
// src/utils/startup-log-boundary.ts
|
|
70
|
+
import { writeSync } from "node:fs";
|
|
71
|
+
function sealStartupLogs() {
|
|
72
|
+
if (failure)
|
|
73
|
+
throw failure;
|
|
74
|
+
if (marker === undefined)
|
|
75
|
+
return;
|
|
76
|
+
try {
|
|
77
|
+
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(marker)) {
|
|
78
|
+
throw new Error("LETTA_STARTUP_LOG_MARKER must be a UUID");
|
|
79
|
+
}
|
|
80
|
+
const bytes = Buffer.from(`
|
|
81
|
+
[letta-startup-end:${marker}]
|
|
82
|
+
`);
|
|
83
|
+
let offset = 0;
|
|
84
|
+
while (offset < bytes.length) {
|
|
85
|
+
const written = writeSync(1, bytes, offset, bytes.length - offset);
|
|
86
|
+
if (written === 0)
|
|
87
|
+
throw new Error("Startup marker write made no progress");
|
|
88
|
+
offset += written;
|
|
89
|
+
}
|
|
90
|
+
marker = undefined;
|
|
91
|
+
} catch (cause) {
|
|
92
|
+
failure = new Error("Failed to seal startup logs", { cause });
|
|
93
|
+
throw failure;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
var marker, ownerPid, failure;
|
|
97
|
+
var init_startup_log_boundary = __esm(() => {
|
|
98
|
+
marker = process.env.LETTA_STARTUP_LOG_MARKER;
|
|
99
|
+
ownerPid = process.env.LETTA_STARTUP_LOG_OWNER_PID;
|
|
100
|
+
delete process.env.LETTA_STARTUP_LOG_MARKER;
|
|
101
|
+
delete process.env.LETTA_STARTUP_LOG_OWNER_PID;
|
|
102
|
+
if (ownerPid !== undefined) {
|
|
103
|
+
if (!/^[1-9][0-9]*$/.test(ownerPid) || !Number.isSafeInteger(Number(ownerPid))) {
|
|
104
|
+
failure = new Error("Failed to seal startup logs", {
|
|
105
|
+
cause: new Error("LETTA_STARTUP_LOG_OWNER_PID must be a positive integer")
|
|
106
|
+
});
|
|
107
|
+
} else if (Number(ownerPid) !== process.pid) {
|
|
108
|
+
marker = undefined;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
|
|
69
113
|
// node_modules/@earendil-works/pi-ai/dist/utils/provider-env.js
|
|
70
114
|
function getBunSandboxEnvValue(name) {
|
|
71
115
|
if (typeof process === "undefined" || !process.versions?.bun || Object.keys(process.env).length > 0) {
|
|
@@ -5471,7 +5515,8 @@ var package_default;
|
|
|
5471
5515
|
var init_package = __esm(() => {
|
|
5472
5516
|
package_default = {
|
|
5473
5517
|
name: "@letta-ai/letta-code",
|
|
5474
|
-
version: "0.32.
|
|
5518
|
+
version: "0.32.3",
|
|
5519
|
+
lettaStartupLogProtocol: 1,
|
|
5475
5520
|
description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
|
|
5476
5521
|
type: "module",
|
|
5477
5522
|
packageManager: "bun@1.3.14",
|
|
@@ -24251,15 +24296,15 @@ var init_memories = __esm(() => {
|
|
|
24251
24296
|
return path3.join(__classPrivateFieldGet3(this, _SessionMemoryStores_workdir, "f"), "memory", resource.name || resource.memory_store_id);
|
|
24252
24297
|
}, _SessionMemoryStores_scanMarker = async function _SessionMemoryStores_scanMarker2(store) {
|
|
24253
24298
|
const local = await store.files.hashtree();
|
|
24254
|
-
const
|
|
24299
|
+
const marker2 = local[MARKER_PATH];
|
|
24255
24300
|
delete local[MARKER_PATH];
|
|
24256
|
-
if (
|
|
24301
|
+
if (marker2 === markerSha(store.memoryStoreId)) {
|
|
24257
24302
|
return { files: local, markerOk: true, distrustReason: null };
|
|
24258
24303
|
}
|
|
24259
24304
|
return {
|
|
24260
24305
|
files: local,
|
|
24261
24306
|
markerOk: false,
|
|
24262
|
-
distrustReason:
|
|
24307
|
+
distrustReason: marker2 !== undefined ? "the marker file does not match this store" : "the marker file is gone"
|
|
24263
24308
|
};
|
|
24264
24309
|
}, _SessionMemoryStores_syncStore = async function _SessionMemoryStores_syncStore2(store, final) {
|
|
24265
24310
|
try {
|
|
@@ -85829,6 +85874,81 @@ var init_context = __esm(() => {
|
|
|
85829
85874
|
context2 = getContext();
|
|
85830
85875
|
});
|
|
85831
85876
|
|
|
85877
|
+
// src/memory-frontmatter.ts
|
|
85878
|
+
function validateMemoryFileFrontmatter({
|
|
85879
|
+
path: path7,
|
|
85880
|
+
content,
|
|
85881
|
+
previousContent,
|
|
85882
|
+
format: format5
|
|
85883
|
+
}) {
|
|
85884
|
+
const errors4 = [];
|
|
85885
|
+
const v2 = format5 === "memfs-v2";
|
|
85886
|
+
const lines = content.split(`
|
|
85887
|
+
`);
|
|
85888
|
+
if (v2 && path7.split("/").at(-1) === "MEMORY.md") {
|
|
85889
|
+
return lines[0] === "---" ? [`${path7}: MEMORY.md must not have frontmatter`] : [];
|
|
85890
|
+
}
|
|
85891
|
+
if (lines[0] !== "---") {
|
|
85892
|
+
return [`${path7}: missing frontmatter (must start with ---)`];
|
|
85893
|
+
}
|
|
85894
|
+
const closing = lines.indexOf("---", 1);
|
|
85895
|
+
if (closing < 0) {
|
|
85896
|
+
return [
|
|
85897
|
+
`${path7}: frontmatter opened but never closed (missing closing ---)`
|
|
85898
|
+
];
|
|
85899
|
+
}
|
|
85900
|
+
function legacyValue(text, key) {
|
|
85901
|
+
const previousLines = text?.split(`
|
|
85902
|
+
`) ?? [];
|
|
85903
|
+
const end = previousLines.indexOf("---", 1);
|
|
85904
|
+
if (end < 0)
|
|
85905
|
+
return "";
|
|
85906
|
+
return previousLines.slice(1, end).filter((line) => line.startsWith(`${key}:`)).map((line) => line.slice(key.length + 1).replace(/^ +| +$/g, "")).join(`
|
|
85907
|
+
`);
|
|
85908
|
+
}
|
|
85909
|
+
if (!v2 && previousContent && legacyValue(previousContent, "read_only") === "true") {
|
|
85910
|
+
return [`${path7}: file is read_only and cannot be modified`];
|
|
85911
|
+
}
|
|
85912
|
+
const seen = new Set;
|
|
85913
|
+
const allowed = v2 ? ["name", "description"] : ["description", "read_only", "limit"];
|
|
85914
|
+
for (const line of lines.slice(1, closing)) {
|
|
85915
|
+
if (!line)
|
|
85916
|
+
continue;
|
|
85917
|
+
if (!v2 && /^[ \t]/.test(line))
|
|
85918
|
+
continue;
|
|
85919
|
+
const separator = line.indexOf(":");
|
|
85920
|
+
const rawKey = separator < 0 ? line : line.slice(0, separator);
|
|
85921
|
+
const key = v2 ? rawKey.replace(/^ +| +$/g, "") : rawKey.replaceAll(" ", "");
|
|
85922
|
+
const value = (separator < 0 ? line : line.slice(separator + 1)).replace(/^ +| +$/g, "");
|
|
85923
|
+
if (!allowed.includes(key)) {
|
|
85924
|
+
errors4.push(`${path7}: unknown frontmatter key '${key}' (allowed: ${allowed.join(" ")})`);
|
|
85925
|
+
continue;
|
|
85926
|
+
}
|
|
85927
|
+
if (v2 && seen.has(key)) {
|
|
85928
|
+
errors4.push(`${path7}: duplicate frontmatter key '${key}'`);
|
|
85929
|
+
}
|
|
85930
|
+
seen.add(key);
|
|
85931
|
+
if (key === "read_only") {
|
|
85932
|
+
if (!previousContent) {
|
|
85933
|
+
errors4.push(`${path7}: 'read_only' is a protected field and cannot be set by the agent`);
|
|
85934
|
+
} else if (value !== legacyValue(previousContent, key)) {
|
|
85935
|
+
errors4.push(`${path7}: 'read_only' is a protected field and cannot be changed by the agent`);
|
|
85936
|
+
}
|
|
85937
|
+
}
|
|
85938
|
+
if ((v2 || key === "description") && (!value || v2 && (value === '""' || value === "''"))) {
|
|
85939
|
+
errors4.push(`${path7}: '${key}' must not be empty`);
|
|
85940
|
+
}
|
|
85941
|
+
}
|
|
85942
|
+
for (const key of v2 ? ["name", "description"] : ["description"]) {
|
|
85943
|
+
if (!seen.has(key))
|
|
85944
|
+
errors4.push(`${path7}: missing required field '${key}'`);
|
|
85945
|
+
}
|
|
85946
|
+
if (!v2 && legacyValue(previousContent, "read_only") && !legacyValue(content, "read_only")) {
|
|
85947
|
+
errors4.push(`${path7}: 'read_only' is a protected field and cannot be removed by the agent`);
|
|
85948
|
+
}
|
|
85949
|
+
return errors4;
|
|
85950
|
+
}
|
|
85951
|
+
|
|
85832
85952
|
// src/memory-constraints.ts
|
|
85833
85953
|
async function validateMemoryTreeConstraints(reader, options) {
|
|
85834
85954
|
const errors4 = [];
|
|
@@ -86242,10 +86362,8 @@ var init_memory_git_hooks = __esm(() => {
|
|
|
86242
86362
|
# Validate frontmatter in staged memory .md files
|
|
86243
86363
|
# Installed by Letta Code CLI
|
|
86244
86364
|
|
|
86245
|
-
AGENT_EDITABLE_KEYS="description"
|
|
86246
|
-
PROTECTED_KEYS="read_only"
|
|
86247
|
-
ALL_KNOWN_KEYS="description read_only limit"
|
|
86248
86365
|
errors=""
|
|
86366
|
+
memory_files=()
|
|
86249
86367
|
|
|
86250
86368
|
memory_layout_policy_file="$(git rev-parse --git-common-dir 2>/dev/null)/${MEMORY_LAYOUT_POLICY}"
|
|
86251
86369
|
memory_layout_policy=$(cat "$memory_layout_policy_file" 2>/dev/null || true)
|
|
@@ -86256,63 +86374,33 @@ validate_memory_constraints() {
|
|
|
86256
86374
|
fi
|
|
86257
86375
|
}
|
|
86258
86376
|
|
|
86259
|
-
|
|
86260
|
-
|
|
86261
|
-
local
|
|
86262
|
-
|
|
86263
|
-
|
|
86264
|
-
|
|
86265
|
-
|
|
86266
|
-
|
|
86267
|
-
|
|
86268
|
-
|
|
86269
|
-
|
|
86270
|
-
|
|
86271
|
-
|
|
86272
|
-
|
|
86273
|
-
|
|
86274
|
-
|
|
86275
|
-
|
|
86276
|
-
|
|
86277
|
-
|
|
86278
|
-
|
|
86279
|
-
|
|
86280
|
-
|
|
86281
|
-
|
|
86282
|
-
|
|
86283
|
-
|
|
86284
|
-
|
|
86285
|
-
|
|
86286
|
-
key=$(echo "$line" | cut -d: -f1 | sed 's/^ *//;s/ *$//')
|
|
86287
|
-
value=$(echo "$line" | cut -d: -f2- | sed 's/^ *//;s/ *$//')
|
|
86288
|
-
case "$key" in
|
|
86289
|
-
name)
|
|
86290
|
-
if [ "$has_name" = "true" ]; then
|
|
86291
|
-
errors="$errors\\n $file: duplicate frontmatter key 'name'"
|
|
86292
|
-
fi
|
|
86293
|
-
has_name=true
|
|
86294
|
-
;;
|
|
86295
|
-
description)
|
|
86296
|
-
if [ "$has_description" = "true" ]; then
|
|
86297
|
-
errors="$errors\\n $file: duplicate frontmatter key 'description'"
|
|
86298
|
-
fi
|
|
86299
|
-
has_description=true
|
|
86300
|
-
;;
|
|
86301
|
-
*)
|
|
86302
|
-
errors="$errors\\n $file: unknown frontmatter key '$key' (allowed: name description)"
|
|
86303
|
-
continue
|
|
86304
|
-
;;
|
|
86305
|
-
esac
|
|
86306
|
-
if [ -z "$value" ] || [ "$value" = '""' ] || [ "$value" = "''" ]; then
|
|
86307
|
-
errors="$errors\\n $file: '$key' must not be empty"
|
|
86308
|
-
fi
|
|
86309
|
-
done <<< "$frontmatter"
|
|
86310
|
-
|
|
86311
|
-
if [ "$has_name" = "false" ]; then
|
|
86312
|
-
errors="$errors\\n $file: missing required field 'name'"
|
|
86313
|
-
fi
|
|
86314
|
-
if [ "$has_description" = "false" ]; then
|
|
86315
|
-
errors="$errors\\n $file: missing required field 'description'"
|
|
86377
|
+
validate_memory_files() {
|
|
86378
|
+
[ "\${#memory_files[@]}" -eq 0 ] && return
|
|
86379
|
+
local result
|
|
86380
|
+
result=$(node - "$1" "\${memory_files[@]}" <<'LETTA_MEMORY_FRONTMATTER'
|
|
86381
|
+
const { execFileSync, spawnSync } = require("node:child_process");
|
|
86382
|
+
const validateMemoryFileFrontmatter = ${validateMemoryFileFrontmatter.toString()};
|
|
86383
|
+
const [format, ...paths] = process.argv.slice(2);
|
|
86384
|
+
try {
|
|
86385
|
+
for (const path of paths) {
|
|
86386
|
+
const content = execFileSync("git", ["show", ":" + path], { encoding: "utf8", maxBuffer: Infinity, stdio: ["ignore", "pipe", "pipe"] });
|
|
86387
|
+
let previousContent = null;
|
|
86388
|
+
if (format === "legacy") {
|
|
86389
|
+
const previous = spawnSync("git", ["show", "HEAD:" + path], { encoding: "utf8", maxBuffer: Infinity, stdio: ["ignore", "pipe", "pipe"] });
|
|
86390
|
+
if (previous.error) throw previous.error;
|
|
86391
|
+
if (previous.status === 0) previousContent = previous.stdout;
|
|
86392
|
+
}
|
|
86393
|
+
const errors = validateMemoryFileFrontmatter({ path, content, previousContent, format });
|
|
86394
|
+
for (const error of errors) console.log(" " + error);
|
|
86395
|
+
}
|
|
86396
|
+
} catch {
|
|
86397
|
+
console.error("Memory validation could not read Git contents. No files were committed.");
|
|
86398
|
+
process.exit(1);
|
|
86399
|
+
}
|
|
86400
|
+
LETTA_MEMORY_FRONTMATTER
|
|
86401
|
+
) || exit $?
|
|
86402
|
+
if [ -n "$result" ]; then
|
|
86403
|
+
errors="$errors\\n$result"
|
|
86316
86404
|
fi
|
|
86317
86405
|
}
|
|
86318
86406
|
|
|
@@ -86354,8 +86442,9 @@ if [ "$use_v2_validation" = "true" ]; then
|
|
|
86354
86442
|
;;
|
|
86355
86443
|
esac
|
|
86356
86444
|
fi
|
|
86357
|
-
[ "$projected" = "true" ] &&
|
|
86445
|
+
[ "$projected" = "true" ] && memory_files+=("$file")
|
|
86358
86446
|
done < <(git ls-files '*.md')
|
|
86447
|
+
validate_memory_files "memfs-v2"
|
|
86359
86448
|
|
|
86360
86449
|
if [ -n "$errors" ]; then
|
|
86361
86450
|
echo "Memory validation failed:"
|
|
@@ -86372,122 +86461,12 @@ for file in $(git diff --cached --name-only --diff-filter=ACMR | grep -E '^(memo
|
|
|
86372
86461
|
errors="$errors\\n $file: invalid skill path (skills must be folders). Use skills/<name>/SKILL.md"
|
|
86373
86462
|
done
|
|
86374
86463
|
|
|
86375
|
-
# Helper: extract a frontmatter value from content
|
|
86376
|
-
get_fm_value() {
|
|
86377
|
-
local content="$1" key="$2"
|
|
86378
|
-
local closing_line
|
|
86379
|
-
closing_line=$(echo "$content" | tail -n +2 | grep -n '^---$' | head -1 | cut -d: -f1)
|
|
86380
|
-
[ -z "$closing_line" ] && return
|
|
86381
|
-
echo "$content" | tail -n +2 | head -n $((closing_line - 1)) | grep "^$key:" | cut -d: -f2- | sed 's/^ *//;s/ *$//'
|
|
86382
|
-
}
|
|
86383
|
-
|
|
86384
86464
|
# Match .md files under system/ or reference/ (with optional memory/ prefix).
|
|
86385
86465
|
# Skip skill SKILL.md files — they use a different frontmatter format.
|
|
86386
86466
|
for file in $(git diff --cached --name-only --diff-filter=ACM | grep -E '^(memory/)?(system|reference)/.*\\.md$'); do
|
|
86387
|
-
|
|
86388
|
-
|
|
86389
|
-
# Frontmatter is required
|
|
86390
|
-
first_line=$(echo "$staged" | head -1)
|
|
86391
|
-
if [ "$first_line" != "---" ]; then
|
|
86392
|
-
errors="$errors\\n $file: missing frontmatter (must start with ---)"
|
|
86393
|
-
continue
|
|
86394
|
-
fi
|
|
86395
|
-
|
|
86396
|
-
# Check frontmatter is properly closed
|
|
86397
|
-
closing_line=$(echo "$staged" | tail -n +2 | grep -n '^---$' | head -1 | cut -d: -f1)
|
|
86398
|
-
if [ -z "$closing_line" ]; then
|
|
86399
|
-
errors="$errors\\n $file: frontmatter opened but never closed (missing closing ---)"
|
|
86400
|
-
continue
|
|
86401
|
-
fi
|
|
86402
|
-
|
|
86403
|
-
# Check read_only protection against HEAD version
|
|
86404
|
-
head_content=$(git show "HEAD:$file" 2>/dev/null || true)
|
|
86405
|
-
if [ -n "$head_content" ]; then
|
|
86406
|
-
head_ro=$(get_fm_value "$head_content" "read_only")
|
|
86407
|
-
if [ "$head_ro" = "true" ]; then
|
|
86408
|
-
errors="$errors\\n $file: file is read_only and cannot be modified"
|
|
86409
|
-
continue
|
|
86410
|
-
fi
|
|
86411
|
-
fi
|
|
86412
|
-
|
|
86413
|
-
# Extract frontmatter lines
|
|
86414
|
-
frontmatter=$(echo "$staged" | tail -n +2 | head -n $((closing_line - 1)))
|
|
86415
|
-
|
|
86416
|
-
# Track required fields
|
|
86417
|
-
has_description=false
|
|
86418
|
-
|
|
86419
|
-
# Validate each line
|
|
86420
|
-
while IFS= read -r line; do
|
|
86421
|
-
[ -z "$line" ] && continue
|
|
86422
|
-
# Skip YAML multiline continuation lines (indented lines that continue a previous value)
|
|
86423
|
-
case "$line" in
|
|
86424
|
-
" "*|$' '*) continue ;;
|
|
86425
|
-
esac
|
|
86426
|
-
|
|
86427
|
-
key=$(echo "$line" | cut -d: -f1 | tr -d ' ')
|
|
86428
|
-
value=$(echo "$line" | cut -d: -f2- | sed 's/^ *//;s/ *$//')
|
|
86429
|
-
|
|
86430
|
-
# Check key is known
|
|
86431
|
-
known=false
|
|
86432
|
-
for k in $ALL_KNOWN_KEYS; do
|
|
86433
|
-
if [ "$key" = "$k" ]; then
|
|
86434
|
-
known=true
|
|
86435
|
-
break
|
|
86436
|
-
fi
|
|
86437
|
-
done
|
|
86438
|
-
if [ "$known" = "false" ]; then
|
|
86439
|
-
errors="$errors\\n $file: unknown frontmatter key '$key' (allowed: $ALL_KNOWN_KEYS)"
|
|
86440
|
-
continue
|
|
86441
|
-
fi
|
|
86442
|
-
|
|
86443
|
-
# Check if agent is trying to modify a protected key
|
|
86444
|
-
for k in $PROTECTED_KEYS; do
|
|
86445
|
-
if [ "$key" = "$k" ]; then
|
|
86446
|
-
# Compare against HEAD — if value changed (or key was added), reject
|
|
86447
|
-
if [ -n "$head_content" ]; then
|
|
86448
|
-
head_val=$(get_fm_value "$head_content" "$key")
|
|
86449
|
-
if [ "$value" != "$head_val" ]; then
|
|
86450
|
-
errors="$errors\\n $file: '$key' is a protected field and cannot be changed by the agent"
|
|
86451
|
-
fi
|
|
86452
|
-
else
|
|
86453
|
-
# New file with read_only — agent shouldn't set this
|
|
86454
|
-
errors="$errors\\n $file: '$key' is a protected field and cannot be set by the agent"
|
|
86455
|
-
fi
|
|
86456
|
-
fi
|
|
86457
|
-
done
|
|
86458
|
-
|
|
86459
|
-
# Validate value types
|
|
86460
|
-
case "$key" in
|
|
86461
|
-
limit)
|
|
86462
|
-
# Legacy field accepted for backward compatibility.
|
|
86463
|
-
;;
|
|
86464
|
-
description)
|
|
86465
|
-
has_description=true
|
|
86466
|
-
if [ -z "$value" ]; then
|
|
86467
|
-
errors="$errors\\n $file: 'description' must not be empty"
|
|
86468
|
-
fi
|
|
86469
|
-
;;
|
|
86470
|
-
esac
|
|
86471
|
-
done <<< "$frontmatter"
|
|
86472
|
-
|
|
86473
|
-
# Check required fields
|
|
86474
|
-
if [ "$has_description" = "false" ]; then
|
|
86475
|
-
errors="$errors\\n $file: missing required field 'description'"
|
|
86476
|
-
fi
|
|
86477
|
-
|
|
86478
|
-
# Check if protected keys were removed (existed in HEAD but not in staged)
|
|
86479
|
-
if [ -n "$head_content" ]; then
|
|
86480
|
-
for k in $PROTECTED_KEYS; do
|
|
86481
|
-
head_val=$(get_fm_value "$head_content" "$k")
|
|
86482
|
-
if [ -n "$head_val" ]; then
|
|
86483
|
-
staged_val=$(get_fm_value "$staged" "$k")
|
|
86484
|
-
if [ -z "$staged_val" ]; then
|
|
86485
|
-
errors="$errors\\n $file: '$k' is a protected field and cannot be removed by the agent"
|
|
86486
|
-
fi
|
|
86487
|
-
fi
|
|
86488
|
-
done
|
|
86489
|
-
fi
|
|
86467
|
+
memory_files+=("$file")
|
|
86490
86468
|
done
|
|
86469
|
+
validate_memory_files "legacy"
|
|
86491
86470
|
|
|
86492
86471
|
if [ -n "$errors" ]; then
|
|
86493
86472
|
echo "Frontmatter validation failed:"
|
|
@@ -86787,6 +86766,12 @@ If the user wants help or to give feedback on Letta Code, point them to discord.
|
|
|
86787
86766
|
|
|
86788
86767
|
Tool results and user messages may include \`<system-reminder>\` tags. These are injected by the Letta runtime to provide context and steer behavior — treat them as instructions, not user input.
|
|
86789
86768
|
|
|
86769
|
+
## Following user requests
|
|
86770
|
+
|
|
86771
|
+
Users may send additional messages while you are working. Treat non-conflicting requests as cumulative, not replacements. If a later message cancels, replaces, or conflicts with earlier work, follow the new instruction while preserving unaffected requests.
|
|
86772
|
+
|
|
86773
|
+
Carry unfinished requests across tool calls, queued-message delivery, and context transitions. Before sending a final response, make sure every outstanding request is answered or completed, or explain what is blocked or explicitly deferred by the user. A successful tool call does not replace an answer the user requested.
|
|
86774
|
+
|
|
86790
86775
|
## Subagents
|
|
86791
86776
|
|
|
86792
86777
|
Delegate to specialized subagents via the Agent tool. Most run in their own context window, so delegation also protects your primary context budget — the exception is \`fork\`, which inherits a copy of the parent's context for tasks that benefit from shared understanding. Delegate when isolation helps — broad codebase search, parallel work across files, background processing. Do work directly when it's contained.
|
|
@@ -86989,6 +86974,12 @@ If the user wants help or to give feedback on Letta Code, point them to discord.
|
|
|
86989
86974
|
|
|
86990
86975
|
Tool results and user messages may include \`<system-reminder>\` tags. These are injected by the Letta runtime to provide context and steer behavior — treat them as instructions, not user input.
|
|
86991
86976
|
|
|
86977
|
+
## Following user requests
|
|
86978
|
+
|
|
86979
|
+
Users may send additional messages while you are working. Treat non-conflicting requests as cumulative, not replacements. If a later message cancels, replaces, or conflicts with earlier work, follow the new instruction while preserving unaffected requests.
|
|
86980
|
+
|
|
86981
|
+
Carry unfinished requests across tool calls, queued-message delivery, and context transitions. Before sending a final response, make sure every outstanding request is answered or completed, or explain what is blocked or explicitly deferred by the user. A successful tool call does not replace an answer the user requested.
|
|
86982
|
+
|
|
86992
86983
|
## Subagents
|
|
86993
86984
|
|
|
86994
86985
|
Delegate to specialized subagents via the Agent tool. Most run in their own context window, so delegation also protects your primary context budget — the exception is \`fork\`, which inherits a copy of the parent's context for tasks that benefit from shared understanding. Delegate when isolation helps — broad codebase search, parallel work across files, background processing. Do work directly when it's contained.
|
|
@@ -87125,6 +87116,12 @@ Your full memory (other than recall) is represented through memory blocks and ex
|
|
|
87125
87116
|
|
|
87126
87117
|
**References as synapses.** Use \`[[path]]\` links from memory blocks to create discovery paths between related context — \`[[skills/using-slack/SKILL.md]]\`, \`[[reference/api.md]]\`, \`[[projects/letta-code]]\`. These references are the synapses of your memory: they should strengthen with use, and the paths you build today should make tomorrow's retrieval faster.
|
|
87127
87118
|
|
|
87119
|
+
# Following user requests
|
|
87120
|
+
|
|
87121
|
+
Users may send additional messages while you are working. Treat non-conflicting requests as cumulative, not replacements. If a later message cancels, replaces, or conflicts with earlier work, follow the new instruction while preserving unaffected requests.
|
|
87122
|
+
|
|
87123
|
+
Carry unfinished requests across tool calls, queued-message delivery, and context transitions. Before sending a final response, make sure every outstanding request is answered or completed, or explain what is blocked or explicitly deferred by the user. A successful tool call does not replace an answer the user requested.
|
|
87124
|
+
|
|
87128
87125
|
# Subagents
|
|
87129
87126
|
|
|
87130
87127
|
Delegate to specialized subagents via the Agent tool. Each gets its own context window, so delegation also protects your primary context budget. Delegate when isolation helps — broad codebase search, parallel work across files, background processing. Do work directly when it's contained.
|
|
@@ -87335,6 +87332,12 @@ If the user wants help or to give feedback on Letta Code, point them to discord.
|
|
|
87335
87332
|
|
|
87336
87333
|
Tool results and user messages may include \`<system-reminder>\` tags. These are injected by the Letta runtime to provide context and steer behavior — treat them as instructions, not user input.
|
|
87337
87334
|
|
|
87335
|
+
## Following user requests
|
|
87336
|
+
|
|
87337
|
+
Users may send additional messages while you are working. Treat non-conflicting requests as cumulative, not replacements. If a later message cancels, replaces, or conflicts with earlier work, follow the new instruction while preserving unaffected requests.
|
|
87338
|
+
|
|
87339
|
+
Carry unfinished requests across tool calls, queued-message delivery, and context transitions. Before sending a final response, make sure every outstanding request is answered or completed, or explain what is blocked or explicitly deferred by the user. A successful tool call does not replace an answer the user requested.
|
|
87340
|
+
|
|
87338
87341
|
## Subagents
|
|
87339
87342
|
|
|
87340
87343
|
Delegate to specialized subagents via the Agent tool. Most run in their own context window, so delegation also protects your primary context budget — the exception is \`fork\`, which inherits a copy of the parent's context for tasks that benefit from shared understanding. Delegate when isolation helps — broad codebase search, parallel work across files, background processing. Do work directly when it's contained.
|
|
@@ -93097,7 +93100,7 @@ function isProjectedMemoryPath(relativePath, allPaths, format5) {
|
|
|
93097
93100
|
}
|
|
93098
93101
|
return true;
|
|
93099
93102
|
}
|
|
93100
|
-
function assertMemfsV2MemoryPathIndexed(memoryDir, relativePath, markerExists = (
|
|
93103
|
+
function assertMemfsV2MemoryPathIndexed(memoryDir, relativePath, markerExists = (marker2) => existsSync7(join10(memoryDir, marker2))) {
|
|
93101
93104
|
const normalized = relativePath.replace(/\\/g, "/");
|
|
93102
93105
|
if (normalized === "MEMORY.md")
|
|
93103
93106
|
return;
|
|
@@ -93108,9 +93111,9 @@ function assertMemfsV2MemoryPathIndexed(memoryDir, relativePath, markerExists =
|
|
|
93108
93111
|
let current = "";
|
|
93109
93112
|
for (const directory of directories) {
|
|
93110
93113
|
current = current ? `${current}/${directory}` : directory;
|
|
93111
|
-
const
|
|
93112
|
-
if (
|
|
93113
|
-
throw new Error(`Memory requires ${
|
|
93114
|
+
const marker2 = `${current}/MEMORY.md`;
|
|
93115
|
+
if (marker2 !== normalized && !markerExists(marker2)) {
|
|
93116
|
+
throw new Error(`Memory requires ${marker2} before writing ${normalized}`);
|
|
93114
93117
|
}
|
|
93115
93118
|
}
|
|
93116
93119
|
}
|
|
@@ -98013,7 +98016,7 @@ Note: \`fork\` cannot be combined with \`agent_id\` or \`conversation_id\`.
|
|
|
98013
98016
|
|
|
98014
98017
|
## Running on Another Computer
|
|
98015
98018
|
|
|
98016
|
-
Pass \`computer\` to run the subagent's turn on another connected computer instead of this machine. Works with any subagent type. The call fails fast if the named device is offline,
|
|
98019
|
+
Pass \`computer\` to run the subagent's turn on another connected computer instead of this machine. Prefer a stable device ID or computer name; these select the freshest online listener for that device. Ephemeral connection IDs are still supported to pin a specific listener. Works with any subagent type. The call fails fast if the named device is offline, the name matches multiple online devices, or the listener is too old to support routing.
|
|
98017
98020
|
|
|
98018
98021
|
\`computer: "cloud"\` provisions a Cloud sandbox for the subagent's conversation and runs the turn there. Sandboxes are per-conversation: this is a separate machine from wherever you are running now, even if you are already in a Cloud sandbox.
|
|
98019
98022
|
|
|
@@ -99750,11 +99753,11 @@ function lockHandlesEqual(left, right) {
|
|
|
99750
99753
|
}
|
|
99751
99754
|
function isLockOwnerProcessAlive(ownerToken) {
|
|
99752
99755
|
const separatorIndex = ownerToken.indexOf("-");
|
|
99753
|
-
const
|
|
99754
|
-
if (!Number.isSafeInteger(
|
|
99756
|
+
const ownerPid2 = Number(separatorIndex === -1 ? ownerToken : ownerToken.slice(0, separatorIndex));
|
|
99757
|
+
if (!Number.isSafeInteger(ownerPid2) || ownerPid2 <= 0)
|
|
99755
99758
|
return false;
|
|
99756
99759
|
try {
|
|
99757
|
-
process.kill(
|
|
99760
|
+
process.kill(ownerPid2, 0);
|
|
99758
99761
|
return true;
|
|
99759
99762
|
} catch (error4) {
|
|
99760
99763
|
return !hasErrorCode(error4, "ESRCH");
|
|
@@ -101986,14 +101989,14 @@ function runExtractionCommand(command, args) {
|
|
|
101986
101989
|
return `${command}: ${formatSpawnFailure(result)}`;
|
|
101987
101990
|
}
|
|
101988
101991
|
function extractTarGzArchive(archivePath, extractDir, assetName) {
|
|
101989
|
-
const
|
|
101992
|
+
const failure2 = runExtractionCommand("tar", [
|
|
101990
101993
|
"xzf",
|
|
101991
101994
|
archivePath,
|
|
101992
101995
|
"-C",
|
|
101993
101996
|
extractDir
|
|
101994
101997
|
]);
|
|
101995
|
-
if (
|
|
101996
|
-
throw new Error(`Failed to extract ${assetName}: ${
|
|
101998
|
+
if (failure2) {
|
|
101999
|
+
throw new Error(`Failed to extract ${assetName}: ${failure2}`);
|
|
101997
102000
|
}
|
|
101998
102001
|
}
|
|
101999
102002
|
function getWindowsTarCommand() {
|
|
@@ -103120,10 +103123,10 @@ function startShellProcess(launcher, options) {
|
|
|
103120
103123
|
} catch (error4) {
|
|
103121
103124
|
completed = true;
|
|
103122
103125
|
cleanup();
|
|
103123
|
-
const
|
|
103124
|
-
rejectCompletion(
|
|
103126
|
+
const failure2 = error4 instanceof Error ? error4 : new Error(String(error4));
|
|
103127
|
+
rejectCompletion(failure2);
|
|
103125
103128
|
completion.catch(() => {});
|
|
103126
|
-
throw
|
|
103129
|
+
throw failure2;
|
|
103127
103130
|
}
|
|
103128
103131
|
if (options.timeoutMs) {
|
|
103129
103132
|
timeoutTimer = setTimeout(() => {
|
|
@@ -106318,6 +106321,88 @@ var init_device_status_cache = __esm(() => {
|
|
|
106318
106321
|
lastDeviceStatusByTransport = new WeakMap;
|
|
106319
106322
|
});
|
|
106320
106323
|
|
|
106324
|
+
// src/tools/toolset-options.ts
|
|
106325
|
+
var TOOLSET_OPTIONS;
|
|
106326
|
+
var init_toolset_options = __esm(() => {
|
|
106327
|
+
TOOLSET_OPTIONS = [
|
|
106328
|
+
{
|
|
106329
|
+
id: "auto",
|
|
106330
|
+
display_name: "Auto",
|
|
106331
|
+
label: "Auto",
|
|
106332
|
+
description: "Auto-select based on the model",
|
|
106333
|
+
is_featured: true
|
|
106334
|
+
},
|
|
106335
|
+
{
|
|
106336
|
+
id: "letta",
|
|
106337
|
+
display_name: "Letta",
|
|
106338
|
+
label: "Letta toolset",
|
|
106339
|
+
description: "Experimental unified toolset for every model",
|
|
106340
|
+
is_featured: true
|
|
106341
|
+
},
|
|
106342
|
+
{
|
|
106343
|
+
id: "none",
|
|
106344
|
+
display_name: "None",
|
|
106345
|
+
label: "None",
|
|
106346
|
+
description: "Remove all Letta Code tools from your agent",
|
|
106347
|
+
is_featured: true
|
|
106348
|
+
},
|
|
106349
|
+
{
|
|
106350
|
+
id: "default",
|
|
106351
|
+
display_name: "Claude",
|
|
106352
|
+
label: "Claude toolset",
|
|
106353
|
+
description: "Optimized for Anthropic models",
|
|
106354
|
+
is_featured: true
|
|
106355
|
+
},
|
|
106356
|
+
{
|
|
106357
|
+
id: "codex",
|
|
106358
|
+
display_name: "Codex",
|
|
106359
|
+
label: "Codex toolset",
|
|
106360
|
+
description: "Optimized for GPT/Codex models",
|
|
106361
|
+
is_featured: true
|
|
106362
|
+
},
|
|
106363
|
+
{
|
|
106364
|
+
id: "gemini",
|
|
106365
|
+
display_name: "Gemini",
|
|
106366
|
+
label: "Gemini toolset",
|
|
106367
|
+
description: "Optimized for Google Gemini models",
|
|
106368
|
+
is_featured: true
|
|
106369
|
+
},
|
|
106370
|
+
{
|
|
106371
|
+
id: "codex_snake",
|
|
106372
|
+
display_name: "Codex (snake_case)",
|
|
106373
|
+
label: "Codex toolset (snake_case)",
|
|
106374
|
+
description: "Optimized for GPT/Codex models (snake_case)",
|
|
106375
|
+
is_featured: false
|
|
106376
|
+
},
|
|
106377
|
+
{
|
|
106378
|
+
id: "gemini_snake",
|
|
106379
|
+
display_name: "Gemini (snake_case)",
|
|
106380
|
+
label: "Gemini toolset (snake_case)",
|
|
106381
|
+
description: "Optimized for Google Gemini models (snake_case)",
|
|
106382
|
+
is_featured: false
|
|
106383
|
+
}
|
|
106384
|
+
];
|
|
106385
|
+
});
|
|
106386
|
+
|
|
106387
|
+
// src/websocket/listener/device-toolset-status.ts
|
|
106388
|
+
function buildDeviceToolsetStatus(agentId, conversationId, conversationRuntime) {
|
|
106389
|
+
let preference = "auto";
|
|
106390
|
+
if (agentId) {
|
|
106391
|
+
try {
|
|
106392
|
+
preference = settingsManager.getToolsetPreference(agentId, conversationId ?? "default");
|
|
106393
|
+
} catch {}
|
|
106394
|
+
}
|
|
106395
|
+
return {
|
|
106396
|
+
current_toolset: conversationRuntime?.currentToolset ?? (preference === "auto" ? null : preference),
|
|
106397
|
+
current_toolset_preference: conversationRuntime?.currentToolset === null ? preference : conversationRuntime?.currentToolsetPreference ?? preference,
|
|
106398
|
+
available_toolsets: [...TOOLSET_OPTIONS]
|
|
106399
|
+
};
|
|
106400
|
+
}
|
|
106401
|
+
var init_device_toolset_status = __esm(() => {
|
|
106402
|
+
init_settings_manager();
|
|
106403
|
+
init_toolset_options();
|
|
106404
|
+
});
|
|
106405
|
+
|
|
106321
106406
|
// src/websocket/listener/listener-constants.ts
|
|
106322
106407
|
var SUPPORTED_REMOTE_COMMANDS;
|
|
106323
106408
|
var init_listener_constants = __esm(() => {
|
|
@@ -106978,8 +107063,7 @@ function buildDeviceStatus(runtime, params) {
|
|
|
106978
107063
|
current_working_directory: fallbackCwd,
|
|
106979
107064
|
git_context: deviceGitContextCache.read(fallbackCwd),
|
|
106980
107065
|
letta_code_version: process.env.npm_package_version || null,
|
|
106981
|
-
|
|
106982
|
-
current_toolset_preference: "auto",
|
|
107066
|
+
...buildDeviceToolsetStatus(null, null),
|
|
106983
107067
|
current_loaded_tools: [],
|
|
106984
107068
|
current_available_skills: [],
|
|
106985
107069
|
background_processes: buildBackgroundProcessSnapshot(),
|
|
@@ -106997,16 +107081,6 @@ function buildDeviceStatus(runtime, params) {
|
|
|
106997
107081
|
const agentId = resolveScopedAgentId(listener, scope);
|
|
106998
107082
|
const conversationId = resolveScopedConversationId(listener, scope);
|
|
106999
107083
|
const conversationRuntime = getConversationRuntime(listener, agentId, conversationId);
|
|
107000
|
-
const toolsetPreference = (() => {
|
|
107001
|
-
if (!agentId) {
|
|
107002
|
-
return "auto";
|
|
107003
|
-
}
|
|
107004
|
-
try {
|
|
107005
|
-
return settingsManager.getToolsetPreference(agentId, conversationId);
|
|
107006
|
-
} catch {
|
|
107007
|
-
return "auto";
|
|
107008
|
-
}
|
|
107009
|
-
})();
|
|
107010
107084
|
const conversationPermissionModeState = getConversationPermissionModeState(listener, agentId, conversationId);
|
|
107011
107085
|
const interruptedCacheActive = hasInterruptedCacheForScope(listener, scope);
|
|
107012
107086
|
const resolvedCwd = conversationRuntime?.activeWorkingDirectory ?? getConversationWorkingDirectory(listener, agentId, conversationId);
|
|
@@ -107031,8 +107105,7 @@ function buildDeviceStatus(runtime, params) {
|
|
|
107031
107105
|
current_working_directory: resolvedCwd,
|
|
107032
107106
|
git_context: deviceGitContextCache.read(resolvedCwd),
|
|
107033
107107
|
letta_code_version: process.env.npm_package_version || null,
|
|
107034
|
-
|
|
107035
|
-
current_toolset_preference: conversationRuntime?.currentToolset === null ? toolsetPreference : conversationRuntime?.currentToolsetPreference ?? toolsetPreference,
|
|
107108
|
+
...buildDeviceToolsetStatus(agentId, conversationId, conversationRuntime),
|
|
107036
107109
|
current_loaded_tools: conversationRuntime?.currentLoadedTools ?? [],
|
|
107037
107110
|
current_available_skills: conversationRuntime?.currentAvailableSkills ?? [],
|
|
107038
107111
|
background_processes: buildBackgroundProcessSnapshot(agentId, conversationId),
|
|
@@ -107468,7 +107541,6 @@ var init_protocol_outbound = __esm(() => {
|
|
|
107468
107541
|
init_constants2();
|
|
107469
107542
|
init_manager();
|
|
107470
107543
|
init_mode();
|
|
107471
|
-
init_settings_manager();
|
|
107472
107544
|
init_error_reporting();
|
|
107473
107545
|
init_debug();
|
|
107474
107546
|
init_background_process_snapshot();
|
|
@@ -107477,6 +107549,7 @@ var init_protocol_outbound = __esm(() => {
|
|
|
107477
107549
|
init_cwd();
|
|
107478
107550
|
init_device_git_context();
|
|
107479
107551
|
init_device_status_cache();
|
|
107552
|
+
init_device_toolset_status();
|
|
107480
107553
|
init_listener_constants();
|
|
107481
107554
|
init_outbound_wire();
|
|
107482
107555
|
init_permission_mode();
|
|
@@ -107760,11 +107833,11 @@ async function runGit2(args, cwd, options = {}) {
|
|
|
107760
107833
|
timeoutMs
|
|
107761
107834
|
});
|
|
107762
107835
|
} catch (error4) {
|
|
107763
|
-
const
|
|
107764
|
-
throw new GitCommandError(
|
|
107765
|
-
stdout:
|
|
107766
|
-
stderr:
|
|
107767
|
-
exitCode: typeof
|
|
107836
|
+
const failure2 = error4;
|
|
107837
|
+
throw new GitCommandError(failure2.killed ? `Timed out running git ${args.join(" ")}` : `Failed to run git ${args.join(" ")}: ${failure2.message}`, args, {
|
|
107838
|
+
stdout: failure2.stdout ?? "",
|
|
107839
|
+
stderr: failure2.stderr ?? "",
|
|
107840
|
+
exitCode: typeof failure2.code === "number" ? failure2.code : null
|
|
107768
107841
|
});
|
|
107769
107842
|
}
|
|
107770
107843
|
if (result.exitCode !== 0 && !options.allowFailure) {
|
|
@@ -112550,12 +112623,12 @@ class MonitorOutputWriter {
|
|
|
112550
112623
|
this.bytesWritten += chunk.length;
|
|
112551
112624
|
return true;
|
|
112552
112625
|
}
|
|
112553
|
-
const
|
|
112626
|
+
const marker2 = Buffer.from(`
|
|
112554
112627
|
[output truncated at ${MONITOR_OUTPUT_FILE_BYTES} bytes]
|
|
112555
112628
|
`, "utf8");
|
|
112556
112629
|
try {
|
|
112557
|
-
const content = validUtf8Prefix(Buffer.concat([readFileSync10(this.path), chunk]), MONITOR_OUTPUT_FILE_BYTES -
|
|
112558
|
-
const truncatedOutput = Buffer.concat([content,
|
|
112630
|
+
const content = validUtf8Prefix(Buffer.concat([readFileSync10(this.path), chunk]), MONITOR_OUTPUT_FILE_BYTES - marker2.length);
|
|
112631
|
+
const truncatedOutput = Buffer.concat([content, marker2]);
|
|
112559
112632
|
writeFileSync9(this.path, truncatedOutput);
|
|
112560
112633
|
this.bytesWritten = truncatedOutput.length;
|
|
112561
112634
|
this.truncated = true;
|
|
@@ -122404,7 +122477,8 @@ var init_skills5 = __esm(() => {
|
|
|
122404
122477
|
init_skill_sources();
|
|
122405
122478
|
LOCAL_AGENT_EXCLUDED_BUNDLED_SKILLS = new Set([
|
|
122406
122479
|
"image-generation",
|
|
122407
|
-
"managing-shared-memory"
|
|
122480
|
+
"managing-shared-memory",
|
|
122481
|
+
"working-across-computers"
|
|
122408
122482
|
]);
|
|
122409
122483
|
PROJECT_SKILLS_DIR = join26(".agents", "skills");
|
|
122410
122484
|
GLOBAL_SKILLS_DIR = join26(process.env.HOME || process.env.USERPROFILE || "~", ".letta/skills");
|
|
@@ -123129,23 +123203,20 @@ function buildAgentTerminalLink(agentId, options, label = agentId) {
|
|
|
123129
123203
|
function buildChatWebUrl(path30) {
|
|
123130
123204
|
return `${CHAT_BASE}${path30}`;
|
|
123131
123205
|
}
|
|
123132
|
-
|
|
123133
|
-
return `${PLATFORM_BASE}${path30}`;
|
|
123134
|
-
}
|
|
123135
|
-
var CHAT_BASE = "https://chat.letta.com", PLATFORM_BASE = "https://platform.letta.com", LETTA_CHAT_API_KEYS_URL;
|
|
123206
|
+
var CHAT_BASE = "https://chat.letta.com", LETTA_CHAT_API_KEYS_URL;
|
|
123136
123207
|
var init_app_urls = __esm(() => {
|
|
123137
123208
|
LETTA_CHAT_API_KEYS_URL = `${CHAT_BASE}/preferences/api-keys`;
|
|
123138
123209
|
});
|
|
123139
123210
|
|
|
123140
123211
|
// src/utils/subagent-stdout-failure.ts
|
|
123141
|
-
import { writeSync } from "node:fs";
|
|
123212
|
+
import { writeSync as writeSync2 } from "node:fs";
|
|
123142
123213
|
function isSubagentStdoutLostError(stderr) {
|
|
123143
123214
|
return stderr.includes(SUBAGENT_STDOUT_LOST_MARKER);
|
|
123144
123215
|
}
|
|
123145
123216
|
function reportSubagentStdoutLoss(detail) {
|
|
123146
123217
|
const suffix = detail === undefined ? "" : ` (${getErrorMessage2(detail)})`;
|
|
123147
123218
|
try {
|
|
123148
|
-
|
|
123219
|
+
writeSync2(2, `${SUBAGENT_STDOUT_LOST_MARKER}${suffix}
|
|
123149
123220
|
`);
|
|
123150
123221
|
} catch {}
|
|
123151
123222
|
}
|
|
@@ -123986,7 +124057,7 @@ async function executeSubagent(type3, config, model, userPrompt, subagentId, isR
|
|
|
123986
124057
|
agentId: parentAgentIdOverride
|
|
123987
124058
|
});
|
|
123988
124059
|
if (primaryModel) {
|
|
123989
|
-
return executeSubagent(type3, config, primaryModel, userPrompt, subagentId, true, signal, undefined, undefined, maxTurns, parentAgentIdOverride, transcriptPath,
|
|
124060
|
+
return executeSubagent(type3, config, primaryModel, userPrompt, subagentId, true, signal, undefined, undefined, maxTurns, parentAgentIdOverride, transcriptPath, memoryScope, systemPromptOverride, environment2, actingUserIdOverride);
|
|
123990
124061
|
}
|
|
123991
124062
|
}
|
|
123992
124063
|
if (!isRetry && isSubagentStdoutLostError(stderr)) {
|
|
@@ -126262,7 +126333,7 @@ var init_Task2 = __esm(() => {
|
|
|
126262
126333
|
},
|
|
126263
126334
|
computer: {
|
|
126264
126335
|
type: "string",
|
|
126265
|
-
description: `Run the subagent on another connected computer instead of this machine.
|
|
126336
|
+
description: `Run the subagent on another connected computer instead of this machine. Prefer a stable device ID or computer name; ephemeral connection IDs are also supported to pin a specific listener. Pass "cloud" to provision a Cloud sandbox for the subagent's conversation. Fails fast if the device is offline or does not support routing. Omit this field to run on the current machine (the default) — only set it when the task specifically needs to run elsewhere.`
|
|
126266
126337
|
}
|
|
126267
126338
|
},
|
|
126268
126339
|
required: ["description", "prompt", "subagent_type"],
|
|
@@ -131714,7 +131785,7 @@ var init_error_formatter = __esm(() => {
|
|
|
131714
131785
|
init_error_context();
|
|
131715
131786
|
init_zai_errors();
|
|
131716
131787
|
LETTA_USAGE_URL = buildChatWebUrl("/preferences/usage");
|
|
131717
|
-
LETTA_AGENTS_URL =
|
|
131788
|
+
LETTA_AGENTS_URL = buildChatWebUrl("/agents");
|
|
131718
131789
|
CLOUDFLARE_EDGE_5XX_MARKER_PATTERN = /(^|\s)(502|52[0-6])\s*<!doctype html|error code\s*(502|52[0-6])/i;
|
|
131719
131790
|
CLOUDFLARE_EDGE_5XX_TITLE_PATTERN = /\|\s*(502|52[0-6])\s*:/i;
|
|
131720
131791
|
CLOUDFLARE_EDGE_5XX_FORMATTED_PATTERN = /\bCloudflare\s+(502|52[0-6])\b/i;
|
|
@@ -134115,6 +134186,40 @@ var init_manager4 = __esm(async () => {
|
|
|
134115
134186
|
MOD_SECRET_NAME_PATTERN = /^[A-Z_][A-Z0-9_]*$/;
|
|
134116
134187
|
});
|
|
134117
134188
|
|
|
134189
|
+
// src/tools/letta-toolset.ts
|
|
134190
|
+
async function loadStartupTools(params) {
|
|
134191
|
+
const { modelIdentifier, toolset, exclude: exclude3 = [] } = params;
|
|
134192
|
+
if (toolset === "letta") {
|
|
134193
|
+
await loadSpecificTools(LETTA_TOOLS.filter((toolName2) => !exclude3.includes(toolName2)));
|
|
134194
|
+
return;
|
|
134195
|
+
}
|
|
134196
|
+
const modelForTools = toolset === "codex" ? "openai/gpt-4" : toolset === "gemini" ? "google_ai/gemini-3.1-pro-preview" : toolset === "default" ? "anthropic/claude-sonnet-4" : modelIdentifier;
|
|
134197
|
+
await loadTools(modelForTools, { exclude: exclude3 });
|
|
134198
|
+
}
|
|
134199
|
+
var LETTA_TOOLS;
|
|
134200
|
+
var init_letta_toolset = __esm(async () => {
|
|
134201
|
+
await init_manager4();
|
|
134202
|
+
LETTA_TOOLS = [
|
|
134203
|
+
"AskUserQuestion",
|
|
134204
|
+
"EnterWorktree",
|
|
134205
|
+
"ExitWorktree",
|
|
134206
|
+
"SetWorkingDirectory",
|
|
134207
|
+
"memory",
|
|
134208
|
+
"Task",
|
|
134209
|
+
"Monitor",
|
|
134210
|
+
"TaskOutput",
|
|
134211
|
+
"TaskStop",
|
|
134212
|
+
"Skill",
|
|
134213
|
+
"exec_command",
|
|
134214
|
+
"write_stdin",
|
|
134215
|
+
"Read",
|
|
134216
|
+
"Edit",
|
|
134217
|
+
"Write",
|
|
134218
|
+
"ViewImage",
|
|
134219
|
+
"UpdatePlan"
|
|
134220
|
+
];
|
|
134221
|
+
});
|
|
134222
|
+
|
|
134118
134223
|
// src/tools/toolset.ts
|
|
134119
134224
|
var exports_toolset = {};
|
|
134120
134225
|
__export(exports_toolset, {
|
|
@@ -134239,6 +134344,9 @@ function getToolNamesForToolset(toolsetName) {
|
|
|
134239
134344
|
case "gemini_snake":
|
|
134240
134345
|
tools = [...GEMINI_DEFAULT_TOOLS];
|
|
134241
134346
|
break;
|
|
134347
|
+
case "letta":
|
|
134348
|
+
tools = [...LETTA_TOOLS];
|
|
134349
|
+
break;
|
|
134242
134350
|
case "none":
|
|
134243
134351
|
tools = [];
|
|
134244
134352
|
break;
|
|
@@ -134521,11 +134629,14 @@ async function forceToolsetSwitch(toolsetName, agentId) {
|
|
|
134521
134629
|
} else if (toolsetName === "gemini_snake") {
|
|
134522
134630
|
await loadTools("google_ai/gemini-3-pro-preview");
|
|
134523
134631
|
modelForLoading = "google_ai/gemini-3-pro-preview";
|
|
134632
|
+
} else if (toolsetName === "letta") {
|
|
134633
|
+
await loadSpecificTools([...LETTA_TOOLS]);
|
|
134634
|
+
modelForLoading = "anthropic/claude-sonnet-4";
|
|
134524
134635
|
} else {
|
|
134525
134636
|
await loadTools("anthropic/claude-sonnet-4");
|
|
134526
134637
|
modelForLoading = "anthropic/claude-sonnet-4";
|
|
134527
134638
|
}
|
|
134528
|
-
const useMemoryPatch = toolsetName === "codex" || toolsetName === "codex_snake";
|
|
134639
|
+
const useMemoryPatch = toolsetName === "codex" || toolsetName === "codex_snake" || toolsetName === "letta";
|
|
134529
134640
|
await ensureCorrectMemoryTool(agentId, modelForLoading, useMemoryPatch);
|
|
134530
134641
|
}
|
|
134531
134642
|
async function switchToolsetForModel(modelIdentifier, agentId, providerType) {
|
|
@@ -134559,6 +134670,7 @@ var init_toolset = __esm(async () => {
|
|
|
134559
134670
|
init_settings_manager();
|
|
134560
134671
|
init_filter();
|
|
134561
134672
|
await __promiseAll([
|
|
134673
|
+
init_letta_toolset(),
|
|
134562
134674
|
init_manager4(),
|
|
134563
134675
|
init_tool_definitions()
|
|
134564
134676
|
]);
|
|
@@ -136745,18 +136857,18 @@ function truncateLocalToolResultTextForRepair(text, maxChars) {
|
|
|
136745
136857
|
[Tool result truncated during local transcript repair: omitted `;
|
|
136746
136858
|
const markerSuffix = ` chars]
|
|
136747
136859
|
`;
|
|
136748
|
-
let
|
|
136749
|
-
let keepChars = Math.max(0, maxChars -
|
|
136860
|
+
let marker2 = `${markerPrefix}${text.length - maxChars}${markerSuffix}`;
|
|
136861
|
+
let keepChars = Math.max(0, maxChars - marker2.length);
|
|
136750
136862
|
let headChars = Math.ceil(keepChars / 2);
|
|
136751
136863
|
let tailChars = keepChars - headChars;
|
|
136752
136864
|
let omittedChars = text.length - headChars - tailChars;
|
|
136753
|
-
|
|
136754
|
-
keepChars = Math.max(0, maxChars -
|
|
136865
|
+
marker2 = `${markerPrefix}${omittedChars}${markerSuffix}`;
|
|
136866
|
+
keepChars = Math.max(0, maxChars - marker2.length);
|
|
136755
136867
|
headChars = Math.ceil(keepChars / 2);
|
|
136756
136868
|
tailChars = keepChars - headChars;
|
|
136757
136869
|
omittedChars = text.length - headChars - tailChars;
|
|
136758
|
-
|
|
136759
|
-
return `${text.slice(0, headChars)}${
|
|
136870
|
+
marker2 = `${markerPrefix}${omittedChars}${markerSuffix}`;
|
|
136871
|
+
return `${text.slice(0, headChars)}${marker2}${tailChars > 0 ? text.slice(-tailChars) : ""}`;
|
|
136760
136872
|
}
|
|
136761
136873
|
function clipOversizedLocalToolResults(messages, options = {}) {
|
|
136762
136874
|
const maxToolResultTextChars = options.maxToolResultTextChars ?? LOCAL_REPAIRED_TOOL_RESULT_TEXT_MAX_CHARS;
|
|
@@ -139229,7 +139341,7 @@ function isContextWindowOverflowError(error4) {
|
|
|
139229
139341
|
"request too large",
|
|
139230
139342
|
"request_too_large",
|
|
139231
139343
|
"model_context_window_exceeded"
|
|
139232
|
-
].some((
|
|
139344
|
+
].some((marker2) => haystack.includes(marker2));
|
|
139233
139345
|
}
|
|
139234
139346
|
var init_context_window_overflow = () => {};
|
|
139235
139347
|
|
|
@@ -139914,7 +140026,6 @@ var init_fake_headless_backend = __esm(() => {
|
|
|
139914
140026
|
remoteMemfs: false,
|
|
139915
140027
|
serverSideToolManagement: false,
|
|
139916
140028
|
serverSecrets: false,
|
|
139917
|
-
agentFileImportExport: false,
|
|
139918
140029
|
promptRecompile: false,
|
|
139919
140030
|
byokProviderRefresh: false,
|
|
139920
140031
|
localModelCatalog: true,
|
|
@@ -141756,10 +141867,10 @@ function middleTruncateText(text, budgetChars, headFrac = 0.3, tailFrac = 0.3) {
|
|
|
141756
141867
|
const head = text.slice(0, headLength);
|
|
141757
141868
|
const tail = tailLength > 0 ? text.slice(-tailLength) : "";
|
|
141758
141869
|
const dropped = Math.max(0, text.length - (head.length + tail.length));
|
|
141759
|
-
const
|
|
141870
|
+
const marker2 = `
|
|
141760
141871
|
[TRUNCATED: dropped ${dropped} middle chars due to context budget]
|
|
141761
141872
|
`;
|
|
141762
|
-
return `${head}${
|
|
141873
|
+
return `${head}${marker2}${tail}`;
|
|
141763
141874
|
}
|
|
141764
141875
|
function textFromUserContent(content) {
|
|
141765
141876
|
const value = content.content;
|
|
@@ -144029,7 +144140,6 @@ class APIBackend {
|
|
|
144029
144140
|
remoteMemfs: true,
|
|
144030
144141
|
serverSideToolManagement: true,
|
|
144031
144142
|
serverSecrets: true,
|
|
144032
|
-
agentFileImportExport: true,
|
|
144033
144143
|
promptRecompile: true,
|
|
144034
144144
|
byokProviderRefresh: true,
|
|
144035
144145
|
localModelCatalog: false,
|
|
@@ -145366,7 +145476,7 @@ var init_args = __esm(() => {
|
|
|
145366
145476
|
mode: "both",
|
|
145367
145477
|
help: {
|
|
145368
145478
|
argLabel: "<name>",
|
|
145369
|
-
description: 'Toolset mode: "auto", "codex", "default", or "gemini" (manual values override model-based auto-selection)'
|
|
145479
|
+
description: 'Toolset mode: "auto", "letta", "codex", "default", or "gemini" (manual values override model-based auto-selection)'
|
|
145370
145480
|
}
|
|
145371
145481
|
},
|
|
145372
145482
|
prompt: {
|
|
@@ -145462,16 +145572,6 @@ var init_args = __esm(() => {
|
|
|
145462
145572
|
}
|
|
145463
145573
|
},
|
|
145464
145574
|
"pre-load-skills": { parser: { type: "string" }, mode: "headless" },
|
|
145465
|
-
"from-af": { parser: { type: "string" }, mode: "both" },
|
|
145466
|
-
import: {
|
|
145467
|
-
parser: { type: "string" },
|
|
145468
|
-
mode: "both",
|
|
145469
|
-
help: {
|
|
145470
|
-
argLabel: "<path>",
|
|
145471
|
-
description: "Create agent from an AgentFile (.af) template",
|
|
145472
|
-
continuationLines: ["Use @author/name to import from the agent registry"]
|
|
145473
|
-
}
|
|
145474
|
-
},
|
|
145475
145575
|
tags: { parser: { type: "string" }, mode: "headless" },
|
|
145476
145576
|
memfs: {
|
|
145477
145577
|
parser: { type: "boolean" },
|
|
@@ -181498,16 +181598,16 @@ function highlightCommand(command) {
|
|
|
181498
181598
|
const firstLine = allLines[0] ?? "";
|
|
181499
181599
|
const heredocMatch = HEREDOC_RE.exec(firstLine);
|
|
181500
181600
|
if (heredocMatch && allLines.length > 2) {
|
|
181501
|
-
const
|
|
181601
|
+
const marker2 = heredocMatch[1] ?? "EOF";
|
|
181502
181602
|
let endIdx = allLines.length - 1;
|
|
181503
181603
|
for (let i4 = allLines.length - 1;i4 > 0; i4--) {
|
|
181504
|
-
if (allLines[i4]?.trim() ===
|
|
181604
|
+
if (allLines[i4]?.trim() === marker2) {
|
|
181505
181605
|
endIdx = i4;
|
|
181506
181606
|
break;
|
|
181507
181607
|
}
|
|
181508
181608
|
}
|
|
181509
181609
|
const bodyLines = allLines.slice(1, endIdx);
|
|
181510
|
-
const terminatorLine = allLines[endIdx] ??
|
|
181610
|
+
const terminatorLine = allLines[endIdx] ?? marker2;
|
|
181511
181611
|
const bashSpans = highlightSingleLineBash(firstLine);
|
|
181512
181612
|
const fileMatch = REDIRECT_FILE_RE.exec(firstLine.slice(0, heredocMatch.index));
|
|
181513
181613
|
const targetFile = fileMatch?.[1];
|
|
@@ -181835,9 +181935,9 @@ var jsx_dev_runtime5, headerRegex, codeBlockOpenRegex, codeBlockCloseRegex, list
|
|
|
181835
181935
|
const listMatch = line.match(listItemRegex);
|
|
181836
181936
|
if (listMatch && listMatch[1] !== undefined && listMatch[2] && listMatch[3] !== undefined) {
|
|
181837
181937
|
const indent = listMatch[1].length;
|
|
181838
|
-
const
|
|
181938
|
+
const marker2 = listMatch[2];
|
|
181839
181939
|
const content = listMatch[3];
|
|
181840
|
-
const bullet = `${
|
|
181940
|
+
const bullet = `${marker2} `;
|
|
181841
181941
|
const bulletWidth = bullet.length;
|
|
181842
181942
|
contentBlocks.push(/* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Box_default, {
|
|
181843
181943
|
paddingLeft: indent,
|
|
@@ -183645,9 +183745,6 @@ function normalizeConversationShorthandFlags(options) {
|
|
|
183645
183745
|
}
|
|
183646
183746
|
return { specifiedConversationId, specifiedAgentId };
|
|
183647
183747
|
}
|
|
183648
|
-
function resolveImportFlagAlias(options) {
|
|
183649
|
-
return options.importFlagValue ?? options.fromAfFlagValue;
|
|
183650
|
-
}
|
|
183651
183748
|
function parsePositiveIntFlag(options) {
|
|
183652
183749
|
const { rawValue, flagName } = options;
|
|
183653
183750
|
if (rawValue === undefined) {
|
|
@@ -183928,14 +184025,14 @@ function runExtractionCommand2(command, args) {
|
|
|
183928
184025
|
return `${command}: ${formatSpawnFailure2(result2)}`;
|
|
183929
184026
|
}
|
|
183930
184027
|
function extractTarGzArchive2(archivePath, extractDir) {
|
|
183931
|
-
const
|
|
184028
|
+
const failure2 = runExtractionCommand2("tar", [
|
|
183932
184029
|
"xzf",
|
|
183933
184030
|
archivePath,
|
|
183934
184031
|
"-C",
|
|
183935
184032
|
extractDir
|
|
183936
184033
|
]);
|
|
183937
|
-
if (
|
|
183938
|
-
throw new Error(`Failed to extract fd: ${
|
|
184034
|
+
if (failure2) {
|
|
184035
|
+
throw new Error(`Failed to extract fd: ${failure2}`);
|
|
183939
184036
|
}
|
|
183940
184037
|
}
|
|
183941
184038
|
function getWindowsTarCommand2() {
|
|
@@ -185112,8 +185209,6 @@ function getLoadingMessage(loadingState, continueSession) {
|
|
|
185112
185209
|
return continueSession ? "Resuming agent..." : "Creating agent...";
|
|
185113
185210
|
case "assembling":
|
|
185114
185211
|
return "Assembling tools...";
|
|
185115
|
-
case "importing":
|
|
185116
|
-
return "Importing agent...";
|
|
185117
185212
|
case "checking":
|
|
185118
185213
|
return "Checking for pending approvals...";
|
|
185119
185214
|
default:
|
|
@@ -185727,8 +185822,8 @@ function validatePrimaryStartupFlagConflicts(options) {
|
|
|
185727
185822
|
message: "--ephemeral cannot be used with --stateless, --memfs, or --memfs-startup"
|
|
185728
185823
|
},
|
|
185729
185824
|
{
|
|
185730
|
-
when: options.
|
|
185731
|
-
message: "--ephemeral cannot be used with --
|
|
185825
|
+
when: options.shouldResume,
|
|
185826
|
+
message: "--ephemeral cannot be used with --resume"
|
|
185732
185827
|
}
|
|
185733
185828
|
]
|
|
185734
185829
|
});
|
|
@@ -185755,10 +185850,6 @@ function validatePrimaryStartupFlagConflicts(options) {
|
|
|
185755
185850
|
when: options.forceNewAgent,
|
|
185756
185851
|
message: "--conversation cannot be used with --new-agent"
|
|
185757
185852
|
},
|
|
185758
|
-
{
|
|
185759
|
-
when: options.importFile,
|
|
185760
|
-
message: "--conversation cannot be used with --import"
|
|
185761
|
-
},
|
|
185762
185853
|
{
|
|
185763
185854
|
when: options.shouldResume,
|
|
185764
185855
|
message: "--conversation cannot be used with --resume"
|
|
@@ -185779,13 +185870,6 @@ function validatePrimaryStartupFlagConflicts(options) {
|
|
|
185779
185870
|
]
|
|
185780
185871
|
});
|
|
185781
185872
|
}
|
|
185782
|
-
function validateRegistryHandleOrThrow(handle2) {
|
|
185783
|
-
const normalized = handle2.startsWith("@") ? handle2.slice(1) : handle2;
|
|
185784
|
-
const parts = normalized.split("/");
|
|
185785
|
-
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
|
185786
|
-
throw new Error(`Invalid registry handle "${handle2}"`);
|
|
185787
|
-
}
|
|
185788
|
-
}
|
|
185789
185873
|
|
|
185790
185874
|
// src/cli/startup-mode.ts
|
|
185791
185875
|
function isHeadlessStartup(flags, stdinIsTTY, firstPositional) {
|
|
@@ -187816,12 +187900,12 @@ function getResolvedEntrypoint() {
|
|
|
187816
187900
|
}
|
|
187817
187901
|
}
|
|
187818
187902
|
function findInstalledPackagePath(resolvedPath) {
|
|
187819
|
-
const
|
|
187820
|
-
const index = resolvedPath.lastIndexOf(
|
|
187903
|
+
const marker2 = `${join42("node_modules", "@letta-ai", "letta-code")}`;
|
|
187904
|
+
const index = resolvedPath.lastIndexOf(marker2);
|
|
187821
187905
|
if (index === -1) {
|
|
187822
187906
|
return null;
|
|
187823
187907
|
}
|
|
187824
|
-
return resolvedPath.slice(0, index +
|
|
187908
|
+
return resolvedPath.slice(0, index + marker2.length);
|
|
187825
187909
|
}
|
|
187826
187910
|
function canWritePath(path33) {
|
|
187827
187911
|
try {
|
|
@@ -191907,14 +191991,14 @@ function firstNonEmptyString2(...values4) {
|
|
|
191907
191991
|
}
|
|
191908
191992
|
return;
|
|
191909
191993
|
}
|
|
191910
|
-
function truncateChannelProgressText(value, maxLength3,
|
|
191994
|
+
function truncateChannelProgressText(value, maxLength3, marker2 = "...") {
|
|
191911
191995
|
if (value.length <= maxLength3) {
|
|
191912
191996
|
return value;
|
|
191913
191997
|
}
|
|
191914
|
-
if (maxLength3 <=
|
|
191915
|
-
return
|
|
191998
|
+
if (maxLength3 <= marker2.length) {
|
|
191999
|
+
return marker2.slice(0, Math.max(0, maxLength3));
|
|
191916
192000
|
}
|
|
191917
|
-
return `${value.slice(0, maxLength3 -
|
|
192001
|
+
return `${value.slice(0, maxLength3 - marker2.length).trimEnd()}${marker2}`;
|
|
191918
192002
|
}
|
|
191919
192003
|
function replaceControlCharacters(value) {
|
|
191920
192004
|
let result2 = "";
|
|
@@ -192313,7 +192397,8 @@ function resolveSlackConcreteActivity(event) {
|
|
|
192313
192397
|
if (event.kind !== "tool" || !isNonEmptyString5(event.toolName) || event.toolName.toLowerCase() === "messagechannel") {
|
|
192314
192398
|
return null;
|
|
192315
192399
|
}
|
|
192316
|
-
|
|
192400
|
+
const descriptions = event.toolBatchTitle !== undefined ? [event.toolBatchTitle] : [event.toolTitle, event.toolDetails];
|
|
192401
|
+
for (const description of descriptions) {
|
|
192317
192402
|
if (!isNonEmptyString5(description)) {
|
|
192318
192403
|
continue;
|
|
192319
192404
|
}
|
|
@@ -195184,6 +195269,12 @@ ${loadingText}`;
|
|
|
195184
195269
|
signatureByConversation.set(stateKey, signature);
|
|
195185
195270
|
const previous = writePromiseByConversation.get(stateKey) ?? Promise.resolve();
|
|
195186
195271
|
const operation = previous.then(async () => {
|
|
195272
|
+
if (footerText && !stateByConversation.get(stateKey)?.isThinkingActive) {
|
|
195273
|
+
if (signatureByConversation.get(stateKey) === signature) {
|
|
195274
|
+
signatureByConversation.delete(stateKey);
|
|
195275
|
+
}
|
|
195276
|
+
return false;
|
|
195277
|
+
}
|
|
195187
195278
|
try {
|
|
195188
195279
|
await setStatus.call(slackClient.assistant?.threads, {
|
|
195189
195280
|
channel_id: source.chatId,
|
|
@@ -195191,6 +195282,16 @@ ${loadingText}`;
|
|
|
195191
195282
|
status: footerText,
|
|
195192
195283
|
...footerText ? { loading_messages: [loadingText] } : {}
|
|
195193
195284
|
});
|
|
195285
|
+
const state = stateByConversation.get(stateKey);
|
|
195286
|
+
if (footerText && state && !state.isThinkingActive) {
|
|
195287
|
+
await setStatus.call(slackClient.assistant?.threads, {
|
|
195288
|
+
channel_id: source.chatId,
|
|
195289
|
+
thread_ts: threadTs,
|
|
195290
|
+
status: ""
|
|
195291
|
+
});
|
|
195292
|
+
clearedStaleReplyKeys.add(replyKey);
|
|
195293
|
+
return true;
|
|
195294
|
+
}
|
|
195194
195295
|
if (footerText)
|
|
195195
195296
|
clearedStaleReplyKeys.delete(replyKey);
|
|
195196
195297
|
else
|
|
@@ -195289,7 +195390,40 @@ ${loadingText}`;
|
|
|
195289
195390
|
await writeStatus(source, "", "", { force: true });
|
|
195290
195391
|
signatureByConversation.delete(key2);
|
|
195291
195392
|
}
|
|
195393
|
+
async function refresh(source) {
|
|
195394
|
+
const key2 = getConversationKey(source);
|
|
195395
|
+
const state = key2 ? stateByConversation.get(key2) : undefined;
|
|
195396
|
+
if (!key2 || !state?.isThinkingActive)
|
|
195397
|
+
return false;
|
|
195398
|
+
await writeStatus(source, state.typingFooterText, state.thinkingText, {
|
|
195399
|
+
force: true
|
|
195400
|
+
});
|
|
195401
|
+
if (stateByConversation.get(key2) === state && state.isThinkingActive) {
|
|
195402
|
+
scheduleKeepalive(key2);
|
|
195403
|
+
}
|
|
195404
|
+
return true;
|
|
195405
|
+
}
|
|
195406
|
+
async function handleLifecycle(event) {
|
|
195407
|
+
if (event.type === "queued") {
|
|
195408
|
+
if (await refresh(event.source))
|
|
195409
|
+
return;
|
|
195410
|
+
if (event.source.showStartupStatus) {
|
|
195411
|
+
await activate(event.source, SLACK_ASSISTANT_STARTUP_STATUS, SLACK_ASSISTANT_STARTUP_STATUS);
|
|
195412
|
+
}
|
|
195413
|
+
return;
|
|
195414
|
+
}
|
|
195415
|
+
for (const source of getUniqueSources(event.sources)) {
|
|
195416
|
+
if (event.type === "processing") {
|
|
195417
|
+
await clearStale(source);
|
|
195418
|
+
} else if (event.stopReason !== "requires_approval") {
|
|
195419
|
+
const remaining = event.remainingSources?.some((other) => other.accountId === source.accountId && getConversationKey(other) === getConversationKey(source) && getLifecycleReplyKey(other) === getLifecycleReplyKey(source));
|
|
195420
|
+
if (!remaining)
|
|
195421
|
+
await deactivate(source);
|
|
195422
|
+
}
|
|
195423
|
+
}
|
|
195424
|
+
}
|
|
195292
195425
|
return {
|
|
195426
|
+
handleLifecycle,
|
|
195293
195427
|
getUniqueSources,
|
|
195294
195428
|
getLifecycleErrorReplyKey,
|
|
195295
195429
|
activate,
|
|
@@ -195329,7 +195463,9 @@ ${loadingText}`;
|
|
|
195329
195463
|
};
|
|
195330
195464
|
}
|
|
195331
195465
|
var SLACK_ASSISTANT_STATUS_KEEPALIVE_MS = 90000;
|
|
195332
|
-
var init_status_controller = () => {
|
|
195466
|
+
var init_status_controller = __esm(() => {
|
|
195467
|
+
init_progress();
|
|
195468
|
+
});
|
|
195333
195469
|
|
|
195334
195470
|
// src/channels/slack/thread-context.ts
|
|
195335
195471
|
function shouldHydrateCurrentSlackMessageAttachments(msg) {
|
|
@@ -195612,19 +195748,19 @@ function createSlackAdapter(config) {
|
|
|
195612
195748
|
if (!running)
|
|
195613
195749
|
return;
|
|
195614
195750
|
if (event.type === "queued") {
|
|
195615
|
-
|
|
195616
|
-
|
|
195617
|
-
|
|
195751
|
+
const showStartupStatus = event.source.showStartupStatus || isSlackFlatChannelThreadOpener(event.source) && isNonEmptyString4(event.source.messageId) && !agentThreadTracker.has(event.source.chatId, event.source.messageId);
|
|
195752
|
+
await status.handleLifecycle({
|
|
195753
|
+
...event,
|
|
195754
|
+
source: { ...event.source, showStartupStatus }
|
|
195755
|
+
});
|
|
195618
195756
|
return;
|
|
195619
195757
|
}
|
|
195620
195758
|
const sources = status.getUniqueSources(event.sources);
|
|
195621
|
-
|
|
195622
|
-
|
|
195759
|
+
await status.handleLifecycle(event);
|
|
195760
|
+
if (event.type === "processing")
|
|
195623
195761
|
return;
|
|
195624
|
-
}
|
|
195625
195762
|
if (event.stopReason === "requires_approval")
|
|
195626
195763
|
return;
|
|
195627
|
-
await Promise.all(sources.map(status.deactivate));
|
|
195628
195764
|
if (!shouldPostSlackTerminalError(event.stopReason))
|
|
195629
195765
|
return;
|
|
195630
195766
|
const errorText = event.error?.trim() ?? "";
|
|
@@ -195899,6 +196035,36 @@ var init_attachment_task = __esm(() => {
|
|
|
195899
196035
|
init_process_manager();
|
|
195900
196036
|
});
|
|
195901
196037
|
|
|
196038
|
+
// src/channels/message-channel-bindings.ts
|
|
196039
|
+
function formatSlackBindingNotice(info, conversationId) {
|
|
196040
|
+
if (!info)
|
|
196041
|
+
return "";
|
|
196042
|
+
if ("unavailable" in info) {
|
|
196043
|
+
return `
|
|
196044
|
+
The message was delivered, but its thread binding could not be checked.`;
|
|
196045
|
+
}
|
|
196046
|
+
if (!info.binding)
|
|
196047
|
+
return `
|
|
196048
|
+
This thread has no incoming-message binding.`;
|
|
196049
|
+
const binding = info.binding;
|
|
196050
|
+
const state = binding.detached ? `This thread is detached (binding: ${binding.conversationId}).` : !binding.enabled ? `Incoming replies are paused for this thread (binding: ${binding.conversationId}).` : binding.conversationId === conversationId ? `Replies in this thread go to this conversation (${conversationId}).` : `Replies in this thread currently go to ${binding.conversationId}; this conversation is ${conversationId}.`;
|
|
196051
|
+
if (binding.conversationId === conversationId)
|
|
196052
|
+
return `
|
|
196053
|
+
${state}`;
|
|
196054
|
+
const action3 = {
|
|
196055
|
+
action: "update-binding",
|
|
196056
|
+
channel: info.channel,
|
|
196057
|
+
accountId: info.accountId,
|
|
196058
|
+
chat_id: info.chatId,
|
|
196059
|
+
threadId: info.threadId,
|
|
196060
|
+
conversationId,
|
|
196061
|
+
expectedConversationId: binding.conversationId
|
|
196062
|
+
};
|
|
196063
|
+
return `
|
|
196064
|
+
${state}
|
|
196065
|
+
To change this thread's destination to this conversation, call MessageChannel with ${JSON.stringify(action3)}. Existing pause/detach settings are preserved.`;
|
|
196066
|
+
}
|
|
196067
|
+
|
|
195902
196068
|
// src/channels/slack/message-action-contract.ts
|
|
195903
196069
|
async function sendSlackMessage(context3) {
|
|
195904
196070
|
const { request, route, adapter, formatText } = context3;
|
|
@@ -195922,7 +196088,8 @@ async function sendSlackMessage(context3) {
|
|
|
195922
196088
|
agentId: route.agentId,
|
|
195923
196089
|
conversationId: route.conversationId
|
|
195924
196090
|
});
|
|
195925
|
-
|
|
196091
|
+
const confirmation = request.mediaPath ? `Attachment sent to slack (message_id: ${result2.messageId})` : `Message sent to slack (message_id: ${result2.messageId})`;
|
|
196092
|
+
return confirmation + formatSlackBindingNotice(result2.bindingInfo, route.conversationId);
|
|
195926
196093
|
}
|
|
195927
196094
|
async function reactInSlack(context3) {
|
|
195928
196095
|
const { request, route, adapter } = context3;
|
|
@@ -195965,11 +196132,26 @@ function createSlackMessageActionAdapter(options = {}) {
|
|
|
195965
196132
|
...options.react ? ["react"] : [],
|
|
195966
196133
|
...options.listCustomEmojis ? ["list-custom-emojis"] : [],
|
|
195967
196134
|
...options.uploadFile ? ["upload-file"] : [],
|
|
195968
|
-
...options.downloadFile ? ["download-file"] : []
|
|
196135
|
+
...options.downloadFile ? ["download-file"] : [],
|
|
196136
|
+
...options.bindings ? ["get-binding", "update-binding"] : []
|
|
195969
196137
|
];
|
|
195970
196138
|
return {
|
|
195971
196139
|
describeMessageTool() {
|
|
195972
196140
|
const properties4 = {};
|
|
196141
|
+
if (options.bindings) {
|
|
196142
|
+
properties4.threadId = {
|
|
196143
|
+
type: ["string", "null"],
|
|
196144
|
+
description: "Thread identifier. Binding actions require an exact Slack thread timestamp, or explicit null for an unthreaded DM."
|
|
196145
|
+
};
|
|
196146
|
+
properties4.conversationId = {
|
|
196147
|
+
type: "string",
|
|
196148
|
+
description: "Destination conversation for update-binding. Must belong to this agent; default selects this agent's default conversation."
|
|
196149
|
+
};
|
|
196150
|
+
properties4.expectedConversationId = {
|
|
196151
|
+
type: "string",
|
|
196152
|
+
description: "Expected current destination for update-binding, from get-binding. A different current binding returns a conflict; an already-matching destination is a no-op."
|
|
196153
|
+
};
|
|
196154
|
+
}
|
|
195973
196155
|
if (options.downloadFile) {
|
|
195974
196156
|
properties4.attachmentId = {
|
|
195975
196157
|
type: "string",
|
|
@@ -196012,6 +196194,7 @@ function createSlackMessageActionAdapter(options = {}) {
|
|
|
196012
196194
|
}
|
|
196013
196195
|
};
|
|
196014
196196
|
}
|
|
196197
|
+
var init_message_action_contract = () => {};
|
|
196015
196198
|
|
|
196016
196199
|
// src/channels/targets.ts
|
|
196017
196200
|
import { existsSync as existsSync37, mkdirSync as mkdirSync21, readFileSync as readFileSync23, writeFileSync as writeFileSync16 } from "node:fs";
|
|
@@ -196391,6 +196574,7 @@ async function downloadSlackFile(context3) {
|
|
|
196391
196574
|
var slackMessageActions;
|
|
196392
196575
|
var init_message_actions2 = __esm(() => {
|
|
196393
196576
|
init_attachment_task();
|
|
196577
|
+
init_message_action_contract();
|
|
196394
196578
|
init_target_resolution();
|
|
196395
196579
|
slackMessageActions = createSlackMessageActionAdapter({
|
|
196396
196580
|
react: true,
|
|
@@ -204807,10 +204991,10 @@ function formatChannelStartupError(error4) {
|
|
|
204807
204991
|
return String(error4);
|
|
204808
204992
|
}
|
|
204809
204993
|
function formatChannelStartupFailures(failures) {
|
|
204810
|
-
const failedChannels = Array.from(new Set(failures.map((
|
|
204811
|
-
const lines = failures.map((
|
|
204812
|
-
const label =
|
|
204813
|
-
return `- ${label}: ${
|
|
204994
|
+
const failedChannels = Array.from(new Set(failures.map((failure2) => failure2.channelId)));
|
|
204995
|
+
const lines = failures.map((failure2) => {
|
|
204996
|
+
const label = failure2.accountId ? `${failure2.channelId}/${failure2.accountId}` : failure2.channelId;
|
|
204997
|
+
return `- ${label}: ${failure2.error}`;
|
|
204814
204998
|
});
|
|
204815
204999
|
return [
|
|
204816
205000
|
"Failed to start requested channel listeners.",
|
|
@@ -217168,7 +217352,7 @@ function shouldProcessInboundMessageDirectly(runtime, parsed) {
|
|
|
217168
217352
|
});
|
|
217169
217353
|
return getListenerBlockedReason(runtime.turnLifecycle.snapshot(), activeScope ? getPendingControlRequestCount(runtime.listener, activeScope) : 0) === null;
|
|
217170
217354
|
}
|
|
217171
|
-
function consumeQueuedTurn(runtime) {
|
|
217355
|
+
function consumeQueuedTurn(runtime, continuation) {
|
|
217172
217356
|
const queuedItems = runtime.queueRuntime.peekReady();
|
|
217173
217357
|
const firstQueuedItem = queuedItems[0];
|
|
217174
217358
|
if (!firstQueuedItem || !isCoalescable(firstQueuedItem.kind)) {
|
|
@@ -217180,15 +217364,22 @@ function consumeQueuedTurn(runtime) {
|
|
|
217180
217364
|
let hasCronPrompt = false;
|
|
217181
217365
|
let hasModContinue = false;
|
|
217182
217366
|
let batchConnectionId;
|
|
217367
|
+
let batchActingUserId = firstQueuedItem.actingUserId;
|
|
217183
217368
|
let batchImageFailureMode = null;
|
|
217184
217369
|
const isNoCoalesce = (candidate) => candidate.kind === "message" && candidate.noCoalesce === true;
|
|
217185
217370
|
for (const item of queuedItems) {
|
|
217371
|
+
if (continuation && item.actingUserId !== continuation.actingUserId) {
|
|
217372
|
+
break;
|
|
217373
|
+
}
|
|
217186
217374
|
if (!isCoalescable(item.kind) || !hasSameQueueScope(firstQueuedItem, item)) {
|
|
217187
217375
|
break;
|
|
217188
217376
|
}
|
|
217189
217377
|
if (queueLen > 0 && (isNoCoalesce(item) || isNoCoalesce(firstQueuedItem))) {
|
|
217190
217378
|
break;
|
|
217191
217379
|
}
|
|
217380
|
+
if (batchActingUserId && item.actingUserId && batchActingUserId !== item.actingUserId) {
|
|
217381
|
+
break;
|
|
217382
|
+
}
|
|
217192
217383
|
if (item.kind === "message") {
|
|
217193
217384
|
const itemConnectionId = runtime.queuedMessagesByItemId.get(item.id)?.connectionId;
|
|
217194
217385
|
if (batchConnectionId !== undefined && itemConnectionId !== undefined && itemConnectionId !== batchConnectionId) {
|
|
@@ -217201,6 +217392,7 @@ function consumeQueuedTurn(runtime) {
|
|
|
217201
217392
|
}
|
|
217202
217393
|
batchImageFailureMode = itemImageFailureMode;
|
|
217203
217394
|
}
|
|
217395
|
+
batchActingUserId ??= item.actingUserId;
|
|
217204
217396
|
queueLen += 1;
|
|
217205
217397
|
if (item.kind === "message") {
|
|
217206
217398
|
hasMessage = true;
|
|
@@ -218066,12 +218258,12 @@ async function resolveDesktopEnvironmentConnectionId(list = listEnvironments) {
|
|
|
218066
218258
|
}
|
|
218067
218259
|
return { connectionId: environment2.connectionId, environment: environment2 };
|
|
218068
218260
|
}
|
|
218069
|
-
async function resolveEnvironmentConnectionId(selector) {
|
|
218261
|
+
async function resolveEnvironmentConnectionId(selector, list = listEnvironments) {
|
|
218070
218262
|
const trimmed = selector.trim();
|
|
218071
218263
|
if (!trimmed) {
|
|
218072
218264
|
throw new Error("Computer selector must not be empty");
|
|
218073
218265
|
}
|
|
218074
|
-
const response = await
|
|
218266
|
+
const response = await list({ limit: 100 });
|
|
218075
218267
|
const matches3 = response.connections.filter((environment3) => {
|
|
218076
218268
|
return environment3.connectionId === trimmed || environment3.id === trimmed || environment3.deviceId === trimmed || environment3.connectionName === trimmed;
|
|
218077
218269
|
});
|
|
@@ -218082,9 +218274,10 @@ async function resolveEnvironmentConnectionId(selector) {
|
|
|
218082
218274
|
if (onlineMatches.length === 0) {
|
|
218083
218275
|
throw new Error(`Computer "${trimmed}" is offline. Matched: ${matches3.map(describeEnvironment).join(", ")}`);
|
|
218084
218276
|
}
|
|
218085
|
-
if (onlineMatches.
|
|
218277
|
+
if (new Set(onlineMatches.map((environment3) => environment3.deviceId)).size > 1) {
|
|
218086
218278
|
throw new Error(`Computer "${trimmed}" is ambiguous. Matched: ${onlineMatches.map(describeEnvironment).join(", ")}`);
|
|
218087
218279
|
}
|
|
218280
|
+
onlineMatches.sort((a2, b3) => Math.max(b3.lastHeartbeat ?? 0, b3.lastSeenAt) - Math.max(a2.lastHeartbeat ?? 0, a2.lastSeenAt));
|
|
218088
218281
|
const environment2 = onlineMatches[0];
|
|
218089
218282
|
if (!environment2) {
|
|
218090
218283
|
throw new Error(`Computer "${trimmed}" is offline`);
|
|
@@ -219014,7 +219207,9 @@ List options:
|
|
|
219014
219207
|
Notes:
|
|
219015
219208
|
- Output is JSON only.
|
|
219016
219209
|
- Uses CLI auth; override with LETTA_API_KEY/LETTA_BASE_URL if needed.
|
|
219017
|
-
- Use letta computers current to get this computer's
|
|
219210
|
+
- Use letta computers current to get this computer's stable deviceId.
|
|
219211
|
+
- Prefer deviceId or connectionName for --computer and Agent(computer=...).
|
|
219212
|
+
connectionId is ephemeral; use it only to pin a specific listener.
|
|
219018
219213
|
- Use --computer cloud to route through the target agent's cloud sandbox.
|
|
219019
219214
|
- Use --computer <name|device-id|connection-id> with headless messaging
|
|
219020
219215
|
to route a message through a specific registered computer.
|
|
@@ -223003,6 +223198,7 @@ var init_protocol_inbound = __esm(() => {
|
|
|
223003
223198
|
"default",
|
|
223004
223199
|
"gemini",
|
|
223005
223200
|
"gemini_snake",
|
|
223201
|
+
"letta",
|
|
223006
223202
|
"none"
|
|
223007
223203
|
]);
|
|
223008
223204
|
});
|
|
@@ -224792,15 +224988,8 @@ function formatToolsetName(id2) {
|
|
|
224792
224988
|
}
|
|
224793
224989
|
var TOOLSET_DISPLAY_NAMES;
|
|
224794
224990
|
var init_toolset_labels = __esm(() => {
|
|
224795
|
-
|
|
224796
|
-
|
|
224797
|
-
codex: "Codex",
|
|
224798
|
-
codex_snake: "Codex (snake_case)",
|
|
224799
|
-
gemini: "Gemini",
|
|
224800
|
-
gemini_snake: "Gemini (snake_case)",
|
|
224801
|
-
none: "None",
|
|
224802
|
-
auto: "Auto"
|
|
224803
|
-
};
|
|
224991
|
+
init_toolset_options();
|
|
224992
|
+
TOOLSET_DISPLAY_NAMES = Object.fromEntries(TOOLSET_OPTIONS.map((option2) => [option2.id, option2.display_name]));
|
|
224804
224993
|
});
|
|
224805
224994
|
|
|
224806
224995
|
// src/mods/disabled-mod-adapter.ts
|
|
@@ -396850,7 +397039,7 @@ function handleModelToolsetCommand(parsed, context3) {
|
|
|
396850
397039
|
});
|
|
396851
397040
|
safeSocketSend(socket, response, "listener_update_model_send_failed", "listener_update_model");
|
|
396852
397041
|
} catch (error4) {
|
|
396853
|
-
const
|
|
397042
|
+
const failure2 = {
|
|
396854
397043
|
type: "update_model_response",
|
|
396855
397044
|
request_id: parsed.request_id,
|
|
396856
397045
|
success: false,
|
|
@@ -396862,7 +397051,7 @@ function handleModelToolsetCommand(parsed, context3) {
|
|
|
396862
397051
|
model_handle: resolvedModel?.handle ?? parsed.payload.model_handle,
|
|
396863
397052
|
error: error4 instanceof Error ? error4.message : "Failed to update model"
|
|
396864
397053
|
};
|
|
396865
|
-
safeSocketSend(socket,
|
|
397054
|
+
safeSocketSend(socket, failure2, "listener_update_model_send_failed", "listener_update_model");
|
|
396866
397055
|
}
|
|
396867
397056
|
});
|
|
396868
397057
|
return true;
|
|
@@ -396880,7 +397069,7 @@ function handleModelToolsetCommand(parsed, context3) {
|
|
|
396880
397069
|
});
|
|
396881
397070
|
safeSocketSend(socket, response, "listener_update_toolset_send_failed", "listener_update_toolset");
|
|
396882
397071
|
} catch (error4) {
|
|
396883
|
-
const
|
|
397072
|
+
const failure2 = {
|
|
396884
397073
|
type: "update_toolset_response",
|
|
396885
397074
|
request_id: parsed.request_id,
|
|
396886
397075
|
success: false,
|
|
@@ -396890,7 +397079,7 @@ function handleModelToolsetCommand(parsed, context3) {
|
|
|
396890
397079
|
},
|
|
396891
397080
|
error: error4 instanceof Error ? error4.message : "Failed to update toolset"
|
|
396892
397081
|
};
|
|
396893
|
-
safeSocketSend(socket,
|
|
397082
|
+
safeSocketSend(socket, failure2, "listener_update_toolset_send_failed", "listener_update_toolset");
|
|
396894
397083
|
}
|
|
396895
397084
|
});
|
|
396896
397085
|
return true;
|
|
@@ -405223,13 +405412,14 @@ async function handleApprovalStop(params) {
|
|
|
405223
405412
|
}
|
|
405224
405413
|
]);
|
|
405225
405414
|
let continuationBatchId = dequeuedBatchId;
|
|
405226
|
-
|
|
405227
|
-
const consumedQueuedTurn = consumeQueuedTurn(runtime
|
|
405415
|
+
const sendOptions = buildSendOptions() ?? {};
|
|
405416
|
+
const consumedQueuedTurn = consumeQueuedTurn(runtime, {
|
|
405417
|
+
actingUserId: sendOptions.actingUserId
|
|
405418
|
+
});
|
|
405228
405419
|
if (consumedQueuedTurn) {
|
|
405229
405420
|
const { dequeuedBatch, queuedTurn } = consumedQueuedTurn;
|
|
405230
405421
|
turnCorrelation?.appendDequeuedBatch(dequeuedBatch.batchId);
|
|
405231
405422
|
continuationBatchId = dequeuedBatch.batchId;
|
|
405232
|
-
continuationActingUserId = queuedTurn.actingUserId;
|
|
405233
405423
|
nextTurnInput = appendQueuedTurnToInput(nextTurnInput, queuedTurn);
|
|
405234
405424
|
emitDequeuedUserMessage(socket, runtime, queuedTurn, dequeuedBatch);
|
|
405235
405425
|
}
|
|
@@ -405244,11 +405434,9 @@ async function handleApprovalStop(params) {
|
|
|
405244
405434
|
});
|
|
405245
405435
|
let sendResult;
|
|
405246
405436
|
try {
|
|
405247
|
-
const sendOptions = buildSendOptions() ?? {};
|
|
405248
405437
|
const imageFailureModesByMessageOtid = mergeImageFailureModesByMessageOtid(sendOptions.imageFailureModesByMessageOtid, nextTurnInput.imageFailureModesByMessageOtid);
|
|
405249
405438
|
sendResult = await sendApprovalContinuation(conversationId, nextInputWithSkillContent, {
|
|
405250
405439
|
...sendOptions,
|
|
405251
|
-
...continuationActingUserId ? { actingUserId: continuationActingUserId } : {},
|
|
405252
405440
|
...imageFailureModesByMessageOtid ? { imageFailureModesByMessageOtid } : {},
|
|
405253
405441
|
...continuationWasFullyAutoHandled ? { allowResponseStateReuse: true } : {}
|
|
405254
405442
|
}, socket, runtime, turnLease);
|
|
@@ -406427,12 +406615,12 @@ function rowToolCalls(row, index, diagnostics2) {
|
|
|
406427
406615
|
}
|
|
406428
406616
|
return calls;
|
|
406429
406617
|
}
|
|
406430
|
-
function
|
|
406618
|
+
function contentText(content) {
|
|
406431
406619
|
if (typeof content === "string") {
|
|
406432
406620
|
if (content.startsWith(CONTENT_JSON_PREFIX)) {
|
|
406433
406621
|
const encoded = content.slice(CONTENT_JSON_PREFIX.length);
|
|
406434
406622
|
try {
|
|
406435
|
-
return
|
|
406623
|
+
return contentText(JSON.parse(encoded));
|
|
406436
406624
|
} catch {
|
|
406437
406625
|
return encoded;
|
|
406438
406626
|
}
|
|
@@ -406518,7 +406706,7 @@ var init_hermes = __esm(() => {
|
|
|
406518
406706
|
});
|
|
406519
406707
|
};
|
|
406520
406708
|
if (row.role === "user") {
|
|
406521
|
-
const content =
|
|
406709
|
+
const content = contentText(row.content);
|
|
406522
406710
|
if (content) {
|
|
406523
406711
|
emit({
|
|
406524
406712
|
type: "message",
|
|
@@ -406538,7 +406726,7 @@ var init_hermes = __esm(() => {
|
|
|
406538
406726
|
...timestamp ? { timestamp } : {}
|
|
406539
406727
|
});
|
|
406540
406728
|
}
|
|
406541
|
-
const content =
|
|
406729
|
+
const content = contentText(row.content);
|
|
406542
406730
|
if (content) {
|
|
406543
406731
|
emit({
|
|
406544
406732
|
type: "message",
|
|
@@ -406561,7 +406749,7 @@ var init_hermes = __esm(() => {
|
|
|
406561
406749
|
if (row.role === "tool") {
|
|
406562
406750
|
emit({
|
|
406563
406751
|
type: "tool_result",
|
|
406564
|
-
content:
|
|
406752
|
+
content: contentText(row.content),
|
|
406565
406753
|
...typeof row.tool_call_id === "string" && row.tool_call_id ? { callId: row.tool_call_id } : {},
|
|
406566
406754
|
...timestamp ? { timestamp } : {}
|
|
406567
406755
|
});
|
|
@@ -407763,28 +407951,28 @@ function truncateText(text2, limit4, strategy) {
|
|
|
407763
407951
|
let low = 0;
|
|
407764
407952
|
let high = Math.min(textLength2 - 1, limit4);
|
|
407765
407953
|
let keep = -1;
|
|
407766
|
-
let
|
|
407954
|
+
let marker2 = "";
|
|
407767
407955
|
while (low <= high) {
|
|
407768
407956
|
const candidateKeep = Math.floor((low + high) / 2);
|
|
407769
407957
|
const candidateMarker = truncationMarker(textLength2 - candidateKeep);
|
|
407770
407958
|
if (candidateKeep + codePointLength(candidateMarker) <= limit4) {
|
|
407771
407959
|
keep = candidateKeep;
|
|
407772
|
-
|
|
407960
|
+
marker2 = candidateMarker;
|
|
407773
407961
|
low = candidateKeep + 1;
|
|
407774
407962
|
} else {
|
|
407775
407963
|
high = candidateKeep - 1;
|
|
407776
407964
|
}
|
|
407777
407965
|
}
|
|
407778
407966
|
if (keep < 0) {
|
|
407779
|
-
|
|
407780
|
-
keep = limit4 - codePointLength(
|
|
407967
|
+
marker2 = sliceCodePoints("…", 0, limit4);
|
|
407968
|
+
keep = limit4 - codePointLength(marker2);
|
|
407781
407969
|
}
|
|
407782
407970
|
if (strategy === "head") {
|
|
407783
|
-
return sliceCodePoints(text2, 0, keep) +
|
|
407971
|
+
return sliceCodePoints(text2, 0, keep) + marker2;
|
|
407784
407972
|
}
|
|
407785
407973
|
const headLength = Math.ceil(keep / 2);
|
|
407786
407974
|
const tailLength = keep - headLength;
|
|
407787
|
-
return sliceCodePoints(text2, 0, headLength) +
|
|
407975
|
+
return sliceCodePoints(text2, 0, headLength) + marker2 + (tailLength > 0 ? sliceCodePoints(text2, textLength2 - tailLength, textLength2) : "");
|
|
407788
407976
|
}
|
|
407789
407977
|
function truncationMarker(remaining) {
|
|
407790
407978
|
return `
|
|
@@ -409095,7 +409283,7 @@ function normalizeReflectionTranscript(entries) {
|
|
|
409095
409283
|
transcript,
|
|
409096
409284
|
sourceContext: { partial: true },
|
|
409097
409285
|
bounds: {
|
|
409098
|
-
toolArguments: { maxCharacters:
|
|
409286
|
+
toolArguments: { maxCharacters: null }
|
|
409099
409287
|
},
|
|
409100
409288
|
filters: { toolResults: "include" }
|
|
409101
409289
|
});
|
|
@@ -409843,7 +410031,7 @@ async function finalizeMultiReflectionPayload(agentId, manifest, success) {
|
|
|
409843
410031
|
await finalizeAutoReflectionPayload(agentId, slice2.conversation_id, slice2.payload_path, slice2.end_snapshot_line, true);
|
|
409844
410032
|
}
|
|
409845
410033
|
}
|
|
409846
|
-
var LEGACY_MESSAGE_ID_STATE_SCHEMA_VERSION = "v2_message_id", REFLECTION_STATE_SCHEMA_VERSION = "v3_assistant_steps", stateMutexes,
|
|
410034
|
+
var LEGACY_MESSAGE_ID_STATE_SCHEMA_VERSION = "v2_message_id", REFLECTION_STATE_SCHEMA_VERSION = "v3_assistant_steps", stateMutexes, REFLECTION_AUTO_QUERIES, REFLECTION_AUTO_RECENT_LIMIT = 20, REFLECTION_AUTO_UNREFLECTED_LIMIT = 20, REFLECTION_AUTO_SEARCH_LIMIT_PER_QUERY = 10, REFLECTION_AUTO_MAX_CATALOG_CANDIDATES = 30, REFLECTION_AUTO_MAX_SELECTED_TRANSCRIPTS = 5;
|
|
409847
410035
|
var init_reflection_transcript = __esm(() => {
|
|
409848
410036
|
init_dist11();
|
|
409849
410037
|
init_memory_filesystem2();
|
|
@@ -410510,7 +410698,7 @@ function isRetryableReflectionArenaModelError(error4) {
|
|
|
410510
410698
|
"insufficient credits",
|
|
410511
410699
|
"exceeded-quota",
|
|
410512
410700
|
"llm_insufficient_credits"
|
|
410513
|
-
].some((
|
|
410701
|
+
].some((marker2) => normalized.includes(marker2));
|
|
410514
410702
|
}
|
|
410515
410703
|
var init_reflection_configuration_error = __esm(() => {
|
|
410516
410704
|
init_strip_ansi();
|
|
@@ -410568,9 +410756,9 @@ function recordReflectionIntegrationRetry(agentId, integration, success, trigger
|
|
|
410568
410756
|
const previous = retries.get(agentId);
|
|
410569
410757
|
const delayMs = previous ? Math.min(previous.delayMs * 2, MAX_RETRY_DELAY_MS2) : INITIAL_RETRY_DELAY_MS3;
|
|
410570
410758
|
const notifiedFailures = previous?.notifiedFailures ?? new Set;
|
|
410571
|
-
const
|
|
410572
|
-
const shouldNotify = triggerSource === "manual" || !notifiedFailures.has(
|
|
410573
|
-
notifiedFailures.add(
|
|
410759
|
+
const failure2 = `${integration.status}:${integration.failurePhase ?? ""}`;
|
|
410760
|
+
const shouldNotify = triggerSource === "manual" || !notifiedFailures.has(failure2);
|
|
410761
|
+
notifiedFailures.add(failure2);
|
|
410574
410762
|
retries.set(agentId, { delayMs, retryAt: now2 + delayMs, notifiedFailures });
|
|
410575
410763
|
return shouldNotify;
|
|
410576
410764
|
}
|
|
@@ -416668,12 +416856,12 @@ async function resolveDirectory(requestedPath, currentBootWorkingDirectory) {
|
|
|
416668
416856
|
return normalizedPath;
|
|
416669
416857
|
}
|
|
416670
416858
|
function getCwdScopeKeyFromRuntimeKey(runtimeKey) {
|
|
416671
|
-
const
|
|
416672
|
-
const markerIndex = runtimeKey.lastIndexOf(
|
|
416859
|
+
const marker2 = "::conversation:";
|
|
416860
|
+
const markerIndex = runtimeKey.lastIndexOf(marker2);
|
|
416673
416861
|
if (!runtimeKey.startsWith("agent:") || markerIndex === -1) {
|
|
416674
416862
|
return null;
|
|
416675
416863
|
}
|
|
416676
|
-
const conversationId = runtimeKey.slice(markerIndex +
|
|
416864
|
+
const conversationId = runtimeKey.slice(markerIndex + marker2.length);
|
|
416677
416865
|
return conversationId === "default" ? runtimeKey : `conversation:${conversationId}`;
|
|
416678
416866
|
}
|
|
416679
416867
|
async function applyScopeUpdates(socket, runtime) {
|
|
@@ -417897,10 +418085,12 @@ function createListenerMessageHandler(params) {
|
|
|
417897
418085
|
} = params;
|
|
417898
418086
|
const connectionId = explicitConnectionId ?? opts.connectionId;
|
|
417899
418087
|
return async (data) => {
|
|
418088
|
+
const lifecycleMessage = parseListenerReadyMessage(data) ?? parseServerLifecycleMessage(data);
|
|
418089
|
+
if (lifecycleMessage?.type !== "pong")
|
|
418090
|
+
sealStartupLogs();
|
|
417900
418091
|
const raw2 = data.toString();
|
|
417901
418092
|
let parsedScope = null;
|
|
417902
418093
|
try {
|
|
417903
|
-
const lifecycleMessage = parseListenerReadyMessage(data) ?? parseServerLifecycleMessage(data);
|
|
417904
418094
|
if (lifecycleMessage) {
|
|
417905
418095
|
if (lifecycleMessage.type === "pong") {
|
|
417906
418096
|
runtime.lastPongAt = Date.now();
|
|
@@ -418445,6 +418635,7 @@ var init_message_router = __esm(async () => {
|
|
|
418445
418635
|
init_system_prompt_warning();
|
|
418446
418636
|
init_settings_manager();
|
|
418447
418637
|
init_debug();
|
|
418638
|
+
init_startup_log_boundary();
|
|
418448
418639
|
init_terminal_handler();
|
|
418449
418640
|
init_agents_conversations();
|
|
418450
418641
|
init_app_server_info();
|
|
@@ -418892,6 +419083,7 @@ function stopRuntime(runtime, suppressCallbacks) {
|
|
|
418892
419083
|
async function startConnectedListenerRuntime(runtime, transport, opts, processQueuedTurn, options = {}) {
|
|
418893
419084
|
if (runtime !== getActiveRuntime() || runtime.intentionallyClosed)
|
|
418894
419085
|
return;
|
|
419086
|
+
sealStartupLogs();
|
|
418895
419087
|
installExternalToolBridge(runtime);
|
|
418896
419088
|
const shouldStartCronScheduler = options.startCronScheduler !== false && process.env.LETTA_DISABLE_CRON_SCHEDULER !== "1";
|
|
418897
419089
|
markListenerConnectionInitialized(runtime, opts.connectionId);
|
|
@@ -419346,6 +419538,7 @@ var init_lifecycle = __esm(async () => {
|
|
|
419346
419538
|
init_telemetry();
|
|
419347
419539
|
init_error_reporting();
|
|
419348
419540
|
init_debug();
|
|
419541
|
+
init_startup_log_boundary();
|
|
419349
419542
|
init_terminal_handler();
|
|
419350
419543
|
init_approval();
|
|
419351
419544
|
init_auth();
|
|
@@ -422827,13 +423020,13 @@ function legacyImageFromPart(part) {
|
|
|
422827
423020
|
const mediaType = typeof part.mediaType === "string" ? part.mediaType : typeof part.mime === "string" ? part.mime : undefined;
|
|
422828
423021
|
const url = typeof part.url === "string" ? part.url : undefined;
|
|
422829
423022
|
if (mediaType?.startsWith("image/") && url?.startsWith("data:")) {
|
|
422830
|
-
const
|
|
422831
|
-
const markerIndex = url.indexOf(
|
|
423023
|
+
const marker2 = ";base64,";
|
|
423024
|
+
const markerIndex = url.indexOf(marker2);
|
|
422832
423025
|
if (markerIndex >= 0) {
|
|
422833
423026
|
return {
|
|
422834
423027
|
type: "image",
|
|
422835
423028
|
mimeType: mediaType,
|
|
422836
|
-
data: url.slice(markerIndex +
|
|
423029
|
+
data: url.slice(markerIndex + marker2.length)
|
|
422837
423030
|
};
|
|
422838
423031
|
}
|
|
422839
423032
|
}
|
|
@@ -440056,7 +440249,7 @@ var init_mcp_client = __esm(() => {
|
|
|
440056
440249
|
init_streamableHttp();
|
|
440057
440250
|
DEFAULT_CLIENT_INFO = {
|
|
440058
440251
|
name: "letta-code",
|
|
440059
|
-
version: "0.32.
|
|
440252
|
+
version: "0.32.3"
|
|
440060
440253
|
};
|
|
440061
440254
|
});
|
|
440062
440255
|
|
|
@@ -443945,7 +444138,7 @@ async function request(path50, init, deps) {
|
|
|
443945
444138
|
async function ensureConversationSandbox(agentId, conversationId, deps = defaultDeps) {
|
|
443946
444139
|
const response = await request(`/v1/agents/${encodeURIComponent(agentId)}/sandboxes`, {
|
|
443947
444140
|
method: "POST",
|
|
443948
|
-
body: JSON.stringify({ conversationId })
|
|
444141
|
+
body: JSON.stringify(conversationId === "default" ? {} : { conversationId })
|
|
443949
444142
|
}, deps);
|
|
443950
444143
|
return await response.json();
|
|
443951
444144
|
}
|
|
@@ -443983,8 +444176,17 @@ Usage:
|
|
|
443983
444176
|
letta sandbox upload <local-path>
|
|
443984
444177
|
letta sandbox download <sandbox-path> [--to <local-path>]
|
|
443985
444178
|
|
|
444179
|
+
Target another conversation (upload or download):
|
|
444180
|
+
letta sandbox upload <local-path> --conversation <conv-id>
|
|
444181
|
+
letta sandbox upload <local-path> --agent <agent-id>
|
|
444182
|
+
|
|
443986
444183
|
Notes:
|
|
443987
|
-
-
|
|
444184
|
+
- Without target flags, uses the active Letta Cloud conversation.
|
|
444185
|
+
- --conversation resolves the owning agent; --agent, if given, must match.
|
|
444186
|
+
- --agent alone selects that agent's main/default sandbox.
|
|
444187
|
+
- --conversation default is also supported and requires explicit --agent.
|
|
444188
|
+
- Target flags override shell/session context without changing it.
|
|
444189
|
+
- Run upload on the computer containing the local file, including a remote subagent.
|
|
443988
444190
|
- Uploads are stored under /root/downloads in the conversation sandbox.
|
|
443989
444191
|
- Downloads are limited to files under /root/downloads.
|
|
443990
444192
|
- Output is JSON only.
|
|
@@ -444021,6 +444223,35 @@ function resolveSandboxSession(env5, fallback) {
|
|
|
444021
444223
|
}
|
|
444022
444224
|
return session2;
|
|
444023
444225
|
}
|
|
444226
|
+
async function resolveSandboxTarget(target2, getCurrentSession, retrieveConversation) {
|
|
444227
|
+
if (target2.agent === undefined && target2.conversation === undefined) {
|
|
444228
|
+
return getCurrentSession();
|
|
444229
|
+
}
|
|
444230
|
+
const agentId = target2.agent?.trim();
|
|
444231
|
+
const conversationId = target2.conversation === undefined && agentId ? "default" : target2.conversation?.trim();
|
|
444232
|
+
if (target2.agent !== undefined && !agentId) {
|
|
444233
|
+
throw new Error("--agent must not be empty");
|
|
444234
|
+
}
|
|
444235
|
+
if (!conversationId || conversationId === "new") {
|
|
444236
|
+
throw new Error("Specify --conversation <conv-id> or --conversation default");
|
|
444237
|
+
}
|
|
444238
|
+
if (agentId && isLocalAgentId(agentId)) {
|
|
444239
|
+
throw new Error("Sandbox file transfer requires a Letta Cloud agent");
|
|
444240
|
+
}
|
|
444241
|
+
if (conversationId === "default") {
|
|
444242
|
+
if (!agentId)
|
|
444243
|
+
throw new Error("--conversation default requires --agent");
|
|
444244
|
+
return { agentId, conversationId };
|
|
444245
|
+
}
|
|
444246
|
+
const conversation = await retrieveConversation(conversationId);
|
|
444247
|
+
if (!conversation.agent_id || isLocalAgentId(conversation.agent_id)) {
|
|
444248
|
+
throw new Error("The target conversation must belong to a Letta Cloud agent");
|
|
444249
|
+
}
|
|
444250
|
+
if (agentId && agentId !== conversation.agent_id) {
|
|
444251
|
+
throw new Error(`Conversation ${conversationId} does not belong to ${agentId}`);
|
|
444252
|
+
}
|
|
444253
|
+
return { agentId: conversation.agent_id, conversationId };
|
|
444254
|
+
}
|
|
444024
444255
|
async function initializeSandboxSettings() {
|
|
444025
444256
|
await settingsManager.initialize();
|
|
444026
444257
|
await settingsManager.loadLocalProjectSettings();
|
|
@@ -444049,24 +444280,37 @@ async function runSandboxSubcommand(argv, deps = {}) {
|
|
|
444049
444280
|
if (!await (deps.isCloud ?? isLettaCloud)()) {
|
|
444050
444281
|
throw new Error("Sandbox file transfer is only available on Letta Cloud");
|
|
444051
444282
|
}
|
|
444052
|
-
const session2 = resolveSandboxSession(process.env, (deps.getLastSession ?? (() => settingsManager.getEffectiveLastSession()))());
|
|
444053
|
-
const
|
|
444283
|
+
const session2 = await resolveSandboxTarget(parsed.values, () => resolveSandboxSession(process.env, (deps.getLastSession ?? (() => settingsManager.getEffectiveLastSession()))()), deps.retrieveConversation ?? (async (id2) => (await getClient()).conversations.retrieve(id2)));
|
|
444284
|
+
const explicitTarget = parsed.values.conversation !== undefined || parsed.values.agent !== undefined;
|
|
444285
|
+
const ensureSandbox = async () => {
|
|
444286
|
+
const sandbox2 = await (deps.ensureSandbox ?? ensureConversationSandbox)(session2.agentId, session2.conversationId);
|
|
444287
|
+
if (explicitTarget && (sandbox2.conversationId ?? "default") !== session2.conversationId) {
|
|
444288
|
+
throw new Error("The server returned a sandbox for a different conversation; no files transferred");
|
|
444289
|
+
}
|
|
444290
|
+
return sandbox2;
|
|
444291
|
+
};
|
|
444292
|
+
const targetOutput = explicitTarget ? session2 : {};
|
|
444054
444293
|
if (action3 === "upload") {
|
|
444055
444294
|
const localPath2 = resolve37(path50);
|
|
444056
444295
|
const fileStat = await (deps.statLocalPath ?? stat17)(localPath2);
|
|
444057
444296
|
if (!fileStat.isFile())
|
|
444058
444297
|
throw new Error(`${localPath2} is not a file`);
|
|
444059
444298
|
const data2 = await (deps.readLocalFile ?? readFile25)(localPath2);
|
|
444060
|
-
const sandbox2 = await ensureSandbox(
|
|
444299
|
+
const sandbox2 = await ensureSandbox();
|
|
444061
444300
|
const result2 = await (deps.uploadFile ?? uploadFileToSandbox)(sandbox2.sandboxId, { blob: new Blob([data2]), name: basename26(localPath2) });
|
|
444062
|
-
console.log(JSON.stringify(result2, null, 2));
|
|
444301
|
+
console.log(JSON.stringify({ ...result2, ...targetOutput }, null, 2));
|
|
444063
444302
|
return 0;
|
|
444064
444303
|
}
|
|
444065
|
-
const sandbox = await ensureSandbox(
|
|
444304
|
+
const sandbox = await ensureSandbox();
|
|
444066
444305
|
const data = await (deps.downloadFile ?? downloadFileFromSandbox)(sandbox.sandboxId, path50);
|
|
444067
444306
|
const localPath = resolve37(parsed.values.to ?? basename26(path50));
|
|
444068
444307
|
await (deps.writeLocalFile ?? writeFile17)(localPath, data);
|
|
444069
|
-
console.log(JSON.stringify({
|
|
444308
|
+
console.log(JSON.stringify({
|
|
444309
|
+
path: localPath,
|
|
444310
|
+
sandboxPath: path50,
|
|
444311
|
+
size: data.byteLength,
|
|
444312
|
+
...targetOutput
|
|
444313
|
+
}, null, 2));
|
|
444070
444314
|
return 0;
|
|
444071
444315
|
} catch (error5) {
|
|
444072
444316
|
console.error(`Error: ${error5 instanceof Error ? error5.message : error5}`);
|
|
@@ -444076,11 +444320,14 @@ async function runSandboxSubcommand(argv, deps = {}) {
|
|
|
444076
444320
|
var SANDBOX_OPTIONS;
|
|
444077
444321
|
var init_sandbox2 = __esm(() => {
|
|
444078
444322
|
init_memory_filesystem2();
|
|
444323
|
+
init_client4();
|
|
444079
444324
|
init_sandbox_files();
|
|
444080
444325
|
init_settings_manager();
|
|
444081
444326
|
SANDBOX_OPTIONS = {
|
|
444082
444327
|
help: { type: "boolean", short: "h" },
|
|
444083
|
-
to: { type: "string" }
|
|
444328
|
+
to: { type: "string" },
|
|
444329
|
+
conversation: { type: "string" },
|
|
444330
|
+
agent: { type: "string" }
|
|
444084
444331
|
};
|
|
444085
444332
|
});
|
|
444086
444333
|
|
|
@@ -446835,13 +447082,13 @@ function parseGitHubSpecifier(input) {
|
|
|
446835
447082
|
if (!owner || !repo)
|
|
446836
447083
|
return null;
|
|
446837
447084
|
const repoUrl = `https://github.com/${owner}/${repo}.git`;
|
|
446838
|
-
const
|
|
446839
|
-
if ((
|
|
447085
|
+
const marker2 = parts[2];
|
|
447086
|
+
if ((marker2 === "tree" || marker2 === "blob") && parts.length >= 4) {
|
|
446840
447087
|
const treePath = parts.slice(3).join("/");
|
|
446841
447088
|
return {
|
|
446842
447089
|
repoUrl,
|
|
446843
447090
|
branch: null,
|
|
446844
|
-
subdir:
|
|
447091
|
+
subdir: marker2 === "blob" ? dirname34(treePath) : treePath
|
|
446845
447092
|
};
|
|
446846
447093
|
}
|
|
446847
447094
|
return { repoUrl, branch: null, subdir: null };
|
|
@@ -449056,43 +449303,43 @@ function addSignalStyle(state, start, style) {
|
|
|
449056
449303
|
}
|
|
449057
449304
|
state.ranges.push({ start, length, style });
|
|
449058
449305
|
}
|
|
449059
|
-
function canOpenSignalMarker(text2, index,
|
|
449060
|
-
const next = text2[index +
|
|
449306
|
+
function canOpenSignalMarker(text2, index, marker2) {
|
|
449307
|
+
const next = text2[index + marker2.delimiter.length];
|
|
449061
449308
|
if (!next || /\s/.test(next)) {
|
|
449062
449309
|
return false;
|
|
449063
449310
|
}
|
|
449064
|
-
if (!
|
|
449311
|
+
if (!marker2.requireWordBoundary) {
|
|
449065
449312
|
return true;
|
|
449066
449313
|
}
|
|
449067
449314
|
const previous = text2[index - 1];
|
|
449068
449315
|
return !isWordLike(previous);
|
|
449069
449316
|
}
|
|
449070
|
-
function isValidSignalMarkerContent(text2, closeIndex, content,
|
|
449317
|
+
function isValidSignalMarkerContent(text2, closeIndex, content, marker2) {
|
|
449071
449318
|
if (content.length === 0 || /^\s|\s$/.test(content)) {
|
|
449072
449319
|
return false;
|
|
449073
449320
|
}
|
|
449074
|
-
if (!
|
|
449321
|
+
if (!marker2.requireWordBoundary) {
|
|
449075
449322
|
return true;
|
|
449076
449323
|
}
|
|
449077
|
-
const next = text2[closeIndex +
|
|
449324
|
+
const next = text2[closeIndex + marker2.delimiter.length];
|
|
449078
449325
|
return !isWordLike(next);
|
|
449079
449326
|
}
|
|
449080
|
-
function findSignalClosingMarker(text2, contentStart,
|
|
449327
|
+
function findSignalClosingMarker(text2, contentStart, marker2) {
|
|
449081
449328
|
let searchIndex = contentStart;
|
|
449082
449329
|
while (searchIndex < text2.length) {
|
|
449083
|
-
const closeIndex = text2.indexOf(
|
|
449330
|
+
const closeIndex = text2.indexOf(marker2.delimiter, searchIndex);
|
|
449084
449331
|
if (closeIndex < 0) {
|
|
449085
449332
|
return -1;
|
|
449086
449333
|
}
|
|
449087
449334
|
if (isEscaped(text2, closeIndex)) {
|
|
449088
|
-
searchIndex = closeIndex +
|
|
449335
|
+
searchIndex = closeIndex + marker2.delimiter.length;
|
|
449089
449336
|
continue;
|
|
449090
449337
|
}
|
|
449091
449338
|
const content = text2.slice(contentStart, closeIndex);
|
|
449092
|
-
if (isValidSignalMarkerContent(text2, closeIndex, content,
|
|
449339
|
+
if (isValidSignalMarkerContent(text2, closeIndex, content, marker2)) {
|
|
449093
449340
|
return closeIndex;
|
|
449094
449341
|
}
|
|
449095
|
-
searchIndex = closeIndex +
|
|
449342
|
+
searchIndex = closeIndex + marker2.delimiter.length;
|
|
449096
449343
|
}
|
|
449097
449344
|
return -1;
|
|
449098
449345
|
}
|
|
@@ -449124,17 +449371,17 @@ function parseSignalInline(text2, state) {
|
|
|
449124
449371
|
continue;
|
|
449125
449372
|
}
|
|
449126
449373
|
}
|
|
449127
|
-
const
|
|
449128
|
-
if (
|
|
449129
|
-
const contentStart = index +
|
|
449130
|
-
const closeIndex = findSignalClosingMarker(text2, contentStart,
|
|
449374
|
+
const marker2 = SIGNAL_INLINE_MARKERS.find((candidate) => text2.startsWith(candidate.delimiter, index) && !isEscaped(text2, index) && canOpenSignalMarker(text2, index, candidate));
|
|
449375
|
+
if (marker2) {
|
|
449376
|
+
const contentStart = index + marker2.delimiter.length;
|
|
449377
|
+
const closeIndex = findSignalClosingMarker(text2, contentStart, marker2);
|
|
449131
449378
|
if (closeIndex >= 0) {
|
|
449132
449379
|
const start = state.text.length;
|
|
449133
449380
|
parseSignalInline(text2.slice(contentStart, closeIndex), state);
|
|
449134
|
-
for (const style of
|
|
449381
|
+
for (const style of marker2.styles) {
|
|
449135
449382
|
addSignalStyle(state, start, style);
|
|
449136
449383
|
}
|
|
449137
|
-
index = closeIndex +
|
|
449384
|
+
index = closeIndex + marker2.delimiter.length;
|
|
449138
449385
|
continue;
|
|
449139
449386
|
}
|
|
449140
449387
|
}
|
|
@@ -449524,6 +449771,38 @@ async function executeMessageChannel(input, options) {
|
|
|
449524
449771
|
const normalized = normalizeMessageChannelInput(input, options.resolver);
|
|
449525
449772
|
if (typeof normalized === "string")
|
|
449526
449773
|
return normalized;
|
|
449774
|
+
if (normalized.action === "get-binding" || normalized.action === "update-binding") {
|
|
449775
|
+
if (normalized.channel !== "slack" || !options.bindings) {
|
|
449776
|
+
return "Error: Binding operations are not supported by this channel host.";
|
|
449777
|
+
}
|
|
449778
|
+
if (!normalized.chatId || normalized.target) {
|
|
449779
|
+
return "Error: Binding operations require chat_id; target is for outbound sends.";
|
|
449780
|
+
}
|
|
449781
|
+
if (input.threadId !== null && (typeof input.threadId !== "string" || !/^\d+\.\d+$/.test(input.threadId))) {
|
|
449782
|
+
return "Error: Binding operations require an exact threadId timestamp, or explicit null for an unthreaded DM.";
|
|
449783
|
+
}
|
|
449784
|
+
const selection = {
|
|
449785
|
+
channel: normalized.channel,
|
|
449786
|
+
accountId: normalized.accountId,
|
|
449787
|
+
chatId: normalized.chatId,
|
|
449788
|
+
threadId: input.threadId
|
|
449789
|
+
};
|
|
449790
|
+
try {
|
|
449791
|
+
if (normalized.action === "get-binding") {
|
|
449792
|
+
return JSON.stringify(await options.bindings.get(selection, options.scope));
|
|
449793
|
+
}
|
|
449794
|
+
const conversationId = firstNonEmptyString4(input.conversationId);
|
|
449795
|
+
const expectedConversationId = firstNonEmptyString4(input.expectedConversationId);
|
|
449796
|
+
if (!conversationId || !expectedConversationId) {
|
|
449797
|
+
return "Error: update-binding requires conversationId and expectedConversationId.";
|
|
449798
|
+
}
|
|
449799
|
+
const result2 = await options.bindings.update({ ...selection, conversationId, expectedConversationId }, options.scope);
|
|
449800
|
+
const prefix = result2.status === "conflict" || result2.status === "not-found" ? "Error: " : "";
|
|
449801
|
+
return `${prefix}${JSON.stringify(result2)}`;
|
|
449802
|
+
} catch (error5) {
|
|
449803
|
+
return `Error: Binding operation failed: ${error5 instanceof Error ? error5.message : "unknown error"}`;
|
|
449804
|
+
}
|
|
449805
|
+
}
|
|
449527
449806
|
if (normalized.channel === "slack" && normalized.action === "download-file" && normalized.target) {
|
|
449528
449807
|
return "Error: Slack download-file requires chat_id from a routed channel context; target is not supported.";
|
|
449529
449808
|
}
|
|
@@ -449538,6 +449817,7 @@ async function executeMessageChannel(input, options) {
|
|
|
449538
449817
|
channel: normalized.channel,
|
|
449539
449818
|
chatId: normalized.chatId,
|
|
449540
449819
|
accountId,
|
|
449820
|
+
...normalized.threadId !== null ? { threadId: normalized.threadId } : {},
|
|
449541
449821
|
scope: options.scope
|
|
449542
449822
|
});
|
|
449543
449823
|
if (typeof context4 === "string")
|
|
@@ -450299,6 +450579,36 @@ var init_channel_rich_draft_streamer = __esm(() => {
|
|
|
450299
450579
|
]);
|
|
450300
450580
|
});
|
|
450301
450581
|
|
|
450582
|
+
// src/channels/gateway-sources.ts
|
|
450583
|
+
function sourceRouteKey(source) {
|
|
450584
|
+
return [
|
|
450585
|
+
source.channel,
|
|
450586
|
+
source.accountId ?? "",
|
|
450587
|
+
source.chatId,
|
|
450588
|
+
source.threadId ?? ""
|
|
450589
|
+
].join(":");
|
|
450590
|
+
}
|
|
450591
|
+
function sourceLifecycleKey(source) {
|
|
450592
|
+
return [
|
|
450593
|
+
sourceRouteKey(source),
|
|
450594
|
+
source.messageId ?? "",
|
|
450595
|
+
source.agentId,
|
|
450596
|
+
source.conversationId
|
|
450597
|
+
].join(":");
|
|
450598
|
+
}
|
|
450599
|
+
function uniqueSourcesBy(sources, getKey) {
|
|
450600
|
+
const byKey = new Map;
|
|
450601
|
+
for (const source of sources)
|
|
450602
|
+
byKey.set(getKey(source), source);
|
|
450603
|
+
return [...byKey.values()];
|
|
450604
|
+
}
|
|
450605
|
+
function uniqueRoutedSources(sources) {
|
|
450606
|
+
return uniqueSourcesBy(sources, sourceRouteKey);
|
|
450607
|
+
}
|
|
450608
|
+
function uniqueLifecycleSources(sources) {
|
|
450609
|
+
return uniqueSourcesBy(sources, sourceLifecycleKey);
|
|
450610
|
+
}
|
|
450611
|
+
|
|
450302
450612
|
// src/channels/progress-builder.ts
|
|
450303
450613
|
function getMessageType(delta2) {
|
|
450304
450614
|
return firstNonEmptyString2(delta2.message_type, delta2.messageType) ?? null;
|
|
@@ -450351,6 +450661,34 @@ function toolNameForMessage(summary) {
|
|
|
450351
450661
|
function createChannelTurnProgressBuilder(options = {}) {
|
|
450352
450662
|
const argumentsByToolCallId = new Map;
|
|
450353
450663
|
const namesByToolCallId = new Map;
|
|
450664
|
+
const batchesByStep = new Map;
|
|
450665
|
+
const batchesByToolCallId = new Map;
|
|
450666
|
+
function addToolBatchTitles(delta2, updates) {
|
|
450667
|
+
const record5 = asRecord4(delta2);
|
|
450668
|
+
if (!record5)
|
|
450669
|
+
return updates;
|
|
450670
|
+
const messageType = getMessageType(record5);
|
|
450671
|
+
const isToolRequest = messageType === "tool_call_message" || messageType === "approval_request_message";
|
|
450672
|
+
const stepKey = isToolRequest ? firstNonEmptyString2(record5.step_id, record5.id) : undefined;
|
|
450673
|
+
let requestBatch = stepKey ? batchesByStep.get(stepKey) : undefined;
|
|
450674
|
+
if (stepKey && !requestBatch) {
|
|
450675
|
+
requestBatch = { title: null };
|
|
450676
|
+
batchesByStep.set(stepKey, requestBatch);
|
|
450677
|
+
}
|
|
450678
|
+
return updates.map((update3) => {
|
|
450679
|
+
if (update3.kind !== "tool")
|
|
450680
|
+
return update3;
|
|
450681
|
+
const batch = (update3.toolCallId ? batchesByToolCallId.get(update3.toolCallId) : undefined) ?? requestBatch;
|
|
450682
|
+
if (!batch)
|
|
450683
|
+
return update3;
|
|
450684
|
+
if (update3.toolCallId)
|
|
450685
|
+
batchesByToolCallId.set(update3.toolCallId, batch);
|
|
450686
|
+
if (batch.title === null && update3.state === "started") {
|
|
450687
|
+
batch.title = firstNonEmptyString2(update3.toolTitle, update3.toolDetails) ?? null;
|
|
450688
|
+
}
|
|
450689
|
+
return { ...update3, toolBatchTitle: batch.title };
|
|
450690
|
+
});
|
|
450691
|
+
}
|
|
450354
450692
|
function extractToolCallSummary(value) {
|
|
450355
450693
|
const record5 = asRecord4(value);
|
|
450356
450694
|
if (!record5) {
|
|
@@ -450667,7 +451005,9 @@ function createChannelTurnProgressBuilder(options = {}) {
|
|
|
450667
451005
|
return [];
|
|
450668
451006
|
}
|
|
450669
451007
|
}
|
|
450670
|
-
return {
|
|
451008
|
+
return {
|
|
451009
|
+
buildUpdates: (delta2) => addToolBatchTitles(delta2, buildUpdates(delta2))
|
|
451010
|
+
};
|
|
450671
451011
|
}
|
|
450672
451012
|
var init_progress_builder = __esm(() => {
|
|
450673
451013
|
init_progress_formatting();
|
|
@@ -450680,34 +451020,6 @@ function runtimeKey(runtime) {
|
|
|
450680
451020
|
function hasAgentRuntime(value) {
|
|
450681
451021
|
return !!value.runtime?.agent_id;
|
|
450682
451022
|
}
|
|
450683
|
-
function sourceRouteKey(source) {
|
|
450684
|
-
return [
|
|
450685
|
-
source.channel,
|
|
450686
|
-
source.accountId ?? "",
|
|
450687
|
-
source.chatId,
|
|
450688
|
-
source.threadId ?? ""
|
|
450689
|
-
].join(":");
|
|
450690
|
-
}
|
|
450691
|
-
function sourceLifecycleKey(source) {
|
|
450692
|
-
return [
|
|
450693
|
-
sourceRouteKey(source),
|
|
450694
|
-
source.messageId ?? "",
|
|
450695
|
-
source.agentId,
|
|
450696
|
-
source.conversationId
|
|
450697
|
-
].join(":");
|
|
450698
|
-
}
|
|
450699
|
-
function uniqueSourcesBy(sources, getKey) {
|
|
450700
|
-
const byKey = new Map;
|
|
450701
|
-
for (const source of sources)
|
|
450702
|
-
byKey.set(getKey(source), source);
|
|
450703
|
-
return [...byKey.values()];
|
|
450704
|
-
}
|
|
450705
|
-
function uniqueRoutedSources(sources) {
|
|
450706
|
-
return uniqueSourcesBy(sources, sourceRouteKey);
|
|
450707
|
-
}
|
|
450708
|
-
function uniqueLifecycleSources(sources) {
|
|
450709
|
-
return uniqueSourcesBy(sources, sourceLifecycleKey);
|
|
450710
|
-
}
|
|
450711
451023
|
function channelTagsForSources(sources) {
|
|
450712
451024
|
return [...new Set(sources.map((source) => `channel:${source.channel}`))];
|
|
450713
451025
|
}
|
|
@@ -450766,6 +451078,7 @@ class ChannelGateway {
|
|
|
450766
451078
|
state.acceptedClientMessageIds.add(delivery.clientMessageId);
|
|
450767
451079
|
return true;
|
|
450768
451080
|
}
|
|
451081
|
+
const workAtSubmit = state.active || state.pendingSourcesByClientMessageId.size > 0;
|
|
450769
451082
|
state.pendingSourcesByClientMessageId.set(delivery.clientMessageId, {
|
|
450770
451083
|
sources: uniqueLifecycleSources(delivery.sources),
|
|
450771
451084
|
disposition: "submitting"
|
|
@@ -450794,6 +451107,8 @@ class ChannelGateway {
|
|
|
450794
451107
|
});
|
|
450795
451108
|
if (!response.accepted) {
|
|
450796
451109
|
state.pendingSourcesByClientMessageId.delete(delivery.clientMessageId);
|
|
451110
|
+
if (workAtSubmit && !state.active)
|
|
451111
|
+
this.finishRejectedDelivery(state, delivery);
|
|
450797
451112
|
return false;
|
|
450798
451113
|
}
|
|
450799
451114
|
this.rememberAcceptedClientMessageId(state, delivery.clientMessageId);
|
|
@@ -450813,9 +451128,28 @@ class ChannelGateway {
|
|
|
450813
451128
|
return true;
|
|
450814
451129
|
} catch (error5) {
|
|
450815
451130
|
state.pendingSourcesByClientMessageId.delete(delivery.clientMessageId);
|
|
451131
|
+
if (workAtSubmit && !state.active)
|
|
451132
|
+
this.finishRejectedDelivery(state, delivery);
|
|
450816
451133
|
throw error5;
|
|
450817
451134
|
}
|
|
450818
451135
|
}
|
|
451136
|
+
remainingSources(state) {
|
|
451137
|
+
return uniqueLifecycleSources([
|
|
451138
|
+
...state.active?.lifecycleSources ?? [],
|
|
451139
|
+
...Array.from(state.pendingSourcesByClientMessageId.values()).flatMap((pending) => pending.sources)
|
|
451140
|
+
]);
|
|
451141
|
+
}
|
|
451142
|
+
finishRejectedDelivery(state, delivery) {
|
|
451143
|
+
const remainingSources = this.remainingSources(state);
|
|
451144
|
+
this.enqueueHook(state, () => this.hooks.onLifecycle({
|
|
451145
|
+
type: "finished",
|
|
451146
|
+
batchId: `channel-${delivery.clientMessageId}`,
|
|
451147
|
+
sources: delivery.sources,
|
|
451148
|
+
stopReason: "cancelled",
|
|
451149
|
+
outcome: "cancelled",
|
|
451150
|
+
remainingSources
|
|
451151
|
+
}));
|
|
451152
|
+
}
|
|
450819
451153
|
adoptQueuedDelivery(delivery) {
|
|
450820
451154
|
const state = this.getState(delivery.runtime);
|
|
450821
451155
|
const sources = uniqueLifecycleSources(delivery.sources);
|
|
@@ -451198,12 +451532,14 @@ class ChannelGateway {
|
|
|
451198
451532
|
this.activateSources(state, firstDequeued.clientMessageId, dequeued.flatMap((entry) => entry.sources));
|
|
451199
451533
|
}
|
|
451200
451534
|
for (const entry of cancelled) {
|
|
451535
|
+
const remainingSources = this.remainingSources(state);
|
|
451201
451536
|
this.enqueueHook(state, () => this.hooks.onLifecycle({
|
|
451202
451537
|
type: "finished",
|
|
451203
451538
|
batchId: `channel-${entry.clientMessageId}`,
|
|
451204
451539
|
sources: entry.sources,
|
|
451205
451540
|
outcome: "cancelled",
|
|
451206
|
-
stopReason: "cancelled"
|
|
451541
|
+
stopReason: "cancelled",
|
|
451542
|
+
...remainingSources.length ? { remainingSources } : {}
|
|
451207
451543
|
}));
|
|
451208
451544
|
}
|
|
451209
451545
|
}
|
|
@@ -451280,12 +451616,14 @@ class ChannelGateway {
|
|
|
451280
451616
|
return;
|
|
451281
451617
|
state.active = null;
|
|
451282
451618
|
active.richDraft?.dispose();
|
|
451619
|
+
const remainingSources = lifecycleOutcome(terminal.stopReason) === "completed" ? this.remainingSources(state) : [];
|
|
451283
451620
|
this.enqueueHook(state, () => this.hooks.onLifecycle({
|
|
451284
451621
|
type: "finished",
|
|
451285
451622
|
batchId: active.batchId,
|
|
451286
451623
|
sources: active.lifecycleSources,
|
|
451287
451624
|
outcome: lifecycleOutcome(terminal.stopReason),
|
|
451288
451625
|
stopReason: terminal.stopReason,
|
|
451626
|
+
...remainingSources.length ? { remainingSources } : {},
|
|
451289
451627
|
...terminal.runId ?? active.runId ? { runId: terminal.runId ?? active.runId } : {},
|
|
451290
451628
|
...terminal.error ? { error: terminal.error } : {}
|
|
451291
451629
|
}));
|
|
@@ -451523,7 +451861,9 @@ Replies to routed Telegram topics stay in the current topic automatically.` : ""
|
|
|
451523
451861
|
hasAction("react") ? 'action="react" with emoji + messageId' : "",
|
|
451524
451862
|
hasAction("list-custom-emojis") ? 'action="list-custom-emojis" to discover the workspace custom emoji names available for reactions' : "",
|
|
451525
451863
|
hasAction("upload-file") ? 'action="upload-file" with media' : "",
|
|
451526
|
-
hasAction("download-file") ? 'action="download-file" with attachmentId + messageId' : ""
|
|
451864
|
+
hasAction("download-file") ? 'action="download-file" with attachmentId + messageId' : "",
|
|
451865
|
+
hasAction("get-binding") ? 'action="get-binding" with chat_id and an explicit threadId (null for an unthreaded DM) to inspect the persisted incoming-message destination without sending' : "",
|
|
451866
|
+
hasAction("update-binding") ? 'action="update-binding" with the same exact thread, conversationId, and expectedConversationId to reassign an existing binding within this agent. It does not send a message, copy history, move queued inputs, change computers, or alter pause/detach settings. Outbound sends never take over an existing binding' : ""
|
|
451527
451867
|
].filter(Boolean) : [];
|
|
451528
451868
|
const slackCapabilityGuidance = slackCapabilities.length > 0 ? `
|
|
451529
451869
|
|
|
@@ -454682,493 +455022,6 @@ var init_headless_tool_events = __esm(async () => {
|
|
|
454682
455022
|
await init_approval_execution();
|
|
454683
455023
|
});
|
|
454684
455024
|
|
|
454685
|
-
// src/skills/builtin/creating-skills/scripts/validate-skill.ts
|
|
454686
|
-
import { existsSync as existsSync65, readFileSync as readFileSync41 } from "node:fs";
|
|
454687
|
-
import { basename as basename29, join as join83, resolve as resolve39 } from "node:path";
|
|
454688
|
-
import { fileURLToPath as fileURLToPath11 } from "node:url";
|
|
454689
|
-
function parseQuotedScalar(value) {
|
|
454690
|
-
if (value.startsWith('"')) {
|
|
454691
|
-
if (!value.endsWith('"') || value.length === 1) {
|
|
454692
|
-
throw new Error("Unterminated double-quoted scalar");
|
|
454693
|
-
}
|
|
454694
|
-
return JSON.parse(value);
|
|
454695
|
-
}
|
|
454696
|
-
if (value.startsWith("'")) {
|
|
454697
|
-
if (!value.endsWith("'") || value.length === 1) {
|
|
454698
|
-
throw new Error("Unterminated single-quoted scalar");
|
|
454699
|
-
}
|
|
454700
|
-
return value.slice(1, -1).replace(/''/g, "'");
|
|
454701
|
-
}
|
|
454702
|
-
return value;
|
|
454703
|
-
}
|
|
454704
|
-
function parseScalar(value) {
|
|
454705
|
-
const trimmed = value.trim();
|
|
454706
|
-
if (!trimmed)
|
|
454707
|
-
return "";
|
|
454708
|
-
if (trimmed === "true")
|
|
454709
|
-
return true;
|
|
454710
|
-
if (trimmed === "false")
|
|
454711
|
-
return false;
|
|
454712
|
-
if (trimmed === "null" || trimmed === "~")
|
|
454713
|
-
return null;
|
|
454714
|
-
if (trimmed.startsWith('"') || trimmed.startsWith("'")) {
|
|
454715
|
-
return parseQuotedScalar(trimmed);
|
|
454716
|
-
}
|
|
454717
|
-
if (trimmed.includes(": ")) {
|
|
454718
|
-
throw new Error(`Unexpected ':' in unquoted scalar: ${trimmed}`);
|
|
454719
|
-
}
|
|
454720
|
-
if (/^-?\d+(?:\.\d+)?$/.test(trimmed)) {
|
|
454721
|
-
return Number(trimmed);
|
|
454722
|
-
}
|
|
454723
|
-
return trimmed;
|
|
454724
|
-
}
|
|
454725
|
-
function parseFrontmatterFallback(source) {
|
|
454726
|
-
const result2 = {};
|
|
454727
|
-
const lines = source.split(/\r?\n/);
|
|
454728
|
-
for (let i4 = 0;i4 < lines.length; i4++) {
|
|
454729
|
-
const line = lines[i4];
|
|
454730
|
-
if (line === undefined)
|
|
454731
|
-
continue;
|
|
454732
|
-
const trimmed = line.trim();
|
|
454733
|
-
if (!trimmed || trimmed.startsWith("#")) {
|
|
454734
|
-
continue;
|
|
454735
|
-
}
|
|
454736
|
-
if (/^\s/.test(line)) {
|
|
454737
|
-
continue;
|
|
454738
|
-
}
|
|
454739
|
-
const colonIndex = line.indexOf(":");
|
|
454740
|
-
if (colonIndex <= 0) {
|
|
454741
|
-
throw new Error(`Invalid frontmatter line: ${line}`);
|
|
454742
|
-
}
|
|
454743
|
-
const key2 = line.slice(0, colonIndex).trim();
|
|
454744
|
-
const rawValue = line.slice(colonIndex + 1).trim();
|
|
454745
|
-
if (!key2) {
|
|
454746
|
-
throw new Error(`Invalid frontmatter line: ${line}`);
|
|
454747
|
-
}
|
|
454748
|
-
if (!rawValue) {
|
|
454749
|
-
result2[key2] = {};
|
|
454750
|
-
continue;
|
|
454751
|
-
}
|
|
454752
|
-
if (rawValue === "|" || rawValue === ">") {
|
|
454753
|
-
const blockLines = [];
|
|
454754
|
-
for (let j2 = i4 + 1;j2 < lines.length; j2++) {
|
|
454755
|
-
const nextLine = lines[j2];
|
|
454756
|
-
if (nextLine === undefined)
|
|
454757
|
-
continue;
|
|
454758
|
-
if (nextLine.trim() && !/^\s/.test(nextLine)) {
|
|
454759
|
-
break;
|
|
454760
|
-
}
|
|
454761
|
-
blockLines.push(nextLine.replace(/^\s{2}/, ""));
|
|
454762
|
-
i4 = j2;
|
|
454763
|
-
}
|
|
454764
|
-
result2[key2] = rawValue === ">" ? blockLines.join(" ").trim() : blockLines.join(`
|
|
454765
|
-
`);
|
|
454766
|
-
continue;
|
|
454767
|
-
}
|
|
454768
|
-
result2[key2] = parseScalar(rawValue);
|
|
454769
|
-
}
|
|
454770
|
-
return result2;
|
|
454771
|
-
}
|
|
454772
|
-
function parseFrontmatter2(source) {
|
|
454773
|
-
const bunParse = globalThis.Bun?.YAML?.parse;
|
|
454774
|
-
if (bunParse) {
|
|
454775
|
-
const parsed = bunParse(source);
|
|
454776
|
-
if (typeof parsed !== "object" || parsed === null) {
|
|
454777
|
-
throw new Error("Frontmatter must be a YAML dictionary");
|
|
454778
|
-
}
|
|
454779
|
-
return parsed;
|
|
454780
|
-
}
|
|
454781
|
-
return parseFrontmatterFallback(source);
|
|
454782
|
-
}
|
|
454783
|
-
function validateSkill(skillPath) {
|
|
454784
|
-
const skillMdPath = join83(skillPath, "SKILL.md");
|
|
454785
|
-
if (!existsSync65(skillMdPath)) {
|
|
454786
|
-
return { valid: false, message: "SKILL.md not found" };
|
|
454787
|
-
}
|
|
454788
|
-
const content = readFileSync41(skillMdPath, "utf-8");
|
|
454789
|
-
if (!content.startsWith("---")) {
|
|
454790
|
-
return { valid: false, message: "No YAML frontmatter found" };
|
|
454791
|
-
}
|
|
454792
|
-
const match3 = content.match(/^---\n([\s\S]*?)\n---/);
|
|
454793
|
-
if (!match3) {
|
|
454794
|
-
return { valid: false, message: "Invalid frontmatter format" };
|
|
454795
|
-
}
|
|
454796
|
-
const frontmatterText = match3[1];
|
|
454797
|
-
let frontmatter;
|
|
454798
|
-
try {
|
|
454799
|
-
frontmatter = parseFrontmatter2(frontmatterText);
|
|
454800
|
-
if (typeof frontmatter !== "object" || frontmatter === null) {
|
|
454801
|
-
return { valid: false, message: "Frontmatter must be a YAML dictionary" };
|
|
454802
|
-
}
|
|
454803
|
-
} catch (e2) {
|
|
454804
|
-
return {
|
|
454805
|
-
valid: false,
|
|
454806
|
-
message: `Invalid YAML in frontmatter: ${e2 instanceof Error ? e2.message : String(e2)}`
|
|
454807
|
-
};
|
|
454808
|
-
}
|
|
454809
|
-
const warnings = [];
|
|
454810
|
-
const unexpectedKeys = Object.keys(frontmatter).filter((key2) => !ALLOWED_PROPERTIES.has(key2));
|
|
454811
|
-
if (unexpectedKeys.length > 0) {
|
|
454812
|
-
warnings.push(`Unknown frontmatter key(s): ${unexpectedKeys.sort().join(", ")}. Known properties are: ${[...ALLOWED_PROPERTIES].sort().join(", ")}`);
|
|
454813
|
-
}
|
|
454814
|
-
if (!("name" in frontmatter)) {
|
|
454815
|
-
return { valid: false, message: "Missing 'name' in frontmatter" };
|
|
454816
|
-
}
|
|
454817
|
-
if (!("description" in frontmatter)) {
|
|
454818
|
-
return { valid: false, message: "Missing 'description' in frontmatter" };
|
|
454819
|
-
}
|
|
454820
|
-
const name = frontmatter.name;
|
|
454821
|
-
if (typeof name !== "string") {
|
|
454822
|
-
return {
|
|
454823
|
-
valid: false,
|
|
454824
|
-
message: `Name must be a string, got ${typeof name}`
|
|
454825
|
-
};
|
|
454826
|
-
}
|
|
454827
|
-
const trimmedName = name.trim();
|
|
454828
|
-
if (trimmedName) {
|
|
454829
|
-
if (!/^[a-z0-9-]+$/.test(trimmedName)) {
|
|
454830
|
-
return {
|
|
454831
|
-
valid: false,
|
|
454832
|
-
message: `Name '${trimmedName}' should be hyphen-case (lowercase letters, digits, and hyphens only)`
|
|
454833
|
-
};
|
|
454834
|
-
}
|
|
454835
|
-
if (trimmedName.startsWith("-") || trimmedName.endsWith("-") || trimmedName.includes("--")) {
|
|
454836
|
-
return {
|
|
454837
|
-
valid: false,
|
|
454838
|
-
message: `Name '${trimmedName}' cannot start/end with hyphen or contain consecutive hyphens`
|
|
454839
|
-
};
|
|
454840
|
-
}
|
|
454841
|
-
if (trimmedName.length > MAX_SKILL_NAME_LENGTH) {
|
|
454842
|
-
return {
|
|
454843
|
-
valid: false,
|
|
454844
|
-
message: `Name is too long (${trimmedName.length} characters). Maximum is ${MAX_SKILL_NAME_LENGTH} characters.`
|
|
454845
|
-
};
|
|
454846
|
-
}
|
|
454847
|
-
const dirName = basename29(skillPath);
|
|
454848
|
-
if (trimmedName !== dirName) {
|
|
454849
|
-
warnings.push(`Name '${trimmedName}' doesn't match directory name '${dirName}'. For portability, these should match.`);
|
|
454850
|
-
}
|
|
454851
|
-
}
|
|
454852
|
-
const description = frontmatter.description;
|
|
454853
|
-
if (typeof description !== "string") {
|
|
454854
|
-
return {
|
|
454855
|
-
valid: false,
|
|
454856
|
-
message: `Description must be a string, got ${typeof description}`
|
|
454857
|
-
};
|
|
454858
|
-
}
|
|
454859
|
-
const trimmedDescription = description.trim();
|
|
454860
|
-
if (trimmedDescription) {
|
|
454861
|
-
if (trimmedDescription.includes("<") || trimmedDescription.includes(">")) {
|
|
454862
|
-
return {
|
|
454863
|
-
valid: false,
|
|
454864
|
-
message: "Description cannot contain angle brackets (< or >)"
|
|
454865
|
-
};
|
|
454866
|
-
}
|
|
454867
|
-
if (trimmedDescription.length > 1024) {
|
|
454868
|
-
return {
|
|
454869
|
-
valid: false,
|
|
454870
|
-
message: `Description is too long (${trimmedDescription.length} characters). Maximum is 1024 characters.`
|
|
454871
|
-
};
|
|
454872
|
-
}
|
|
454873
|
-
}
|
|
454874
|
-
return {
|
|
454875
|
-
valid: true,
|
|
454876
|
-
message: "Skill is valid!",
|
|
454877
|
-
warnings: warnings.length > 0 ? warnings : undefined
|
|
454878
|
-
};
|
|
454879
|
-
}
|
|
454880
|
-
function isMainModule() {
|
|
454881
|
-
const entrypoint = process.argv[1];
|
|
454882
|
-
return entrypoint ? resolve39(entrypoint) === fileURLToPath11(import.meta.url) : false;
|
|
454883
|
-
}
|
|
454884
|
-
var ALLOWED_PROPERTIES, MAX_SKILL_NAME_LENGTH = 64;
|
|
454885
|
-
var init_validate_skill = __esm(() => {
|
|
454886
|
-
ALLOWED_PROPERTIES = new Set([
|
|
454887
|
-
"name",
|
|
454888
|
-
"description",
|
|
454889
|
-
"license",
|
|
454890
|
-
"compatibility",
|
|
454891
|
-
"metadata",
|
|
454892
|
-
"allowed-tools"
|
|
454893
|
-
]);
|
|
454894
|
-
if (isMainModule()) {
|
|
454895
|
-
const args = process.argv.slice(2);
|
|
454896
|
-
if (args.length !== 1) {
|
|
454897
|
-
console.log("Usage: npx tsx validate-skill.ts <skill-directory>");
|
|
454898
|
-
process.exit(1);
|
|
454899
|
-
}
|
|
454900
|
-
const { valid: valid2, message, warnings } = validateSkill(args[0]);
|
|
454901
|
-
console.log(message);
|
|
454902
|
-
if (warnings && warnings.length > 0) {
|
|
454903
|
-
for (const warning of warnings) {
|
|
454904
|
-
console.warn(`Warning: ${warning}`);
|
|
454905
|
-
}
|
|
454906
|
-
}
|
|
454907
|
-
process.exit(valid2 ? 0 : 1);
|
|
454908
|
-
}
|
|
454909
|
-
});
|
|
454910
|
-
|
|
454911
|
-
// src/agent/github-utils.ts
|
|
454912
|
-
var exports_github_utils = {};
|
|
454913
|
-
__export(exports_github_utils, {
|
|
454914
|
-
parseDirNames: () => parseDirNames,
|
|
454915
|
-
fetchGitHubContents: () => fetchGitHubContents
|
|
454916
|
-
});
|
|
454917
|
-
async function fetchGitHubContents(owner, repo, branch, path50) {
|
|
454918
|
-
const apiPath = path50 ? `repos/${owner}/${repo}/contents/${path50}?ref=${branch}` : `repos/${owner}/${repo}/contents?ref=${branch}`;
|
|
454919
|
-
try {
|
|
454920
|
-
const { execFileSync: execFileSync7 } = await import("node:child_process");
|
|
454921
|
-
const result2 = execFileSync7("gh", ["api", apiPath], {
|
|
454922
|
-
encoding: "utf-8",
|
|
454923
|
-
stdio: ["pipe", "pipe", "ignore"]
|
|
454924
|
-
});
|
|
454925
|
-
return JSON.parse(result2);
|
|
454926
|
-
} catch {}
|
|
454927
|
-
const url2 = `https://api.github.com/repos/${owner}/${repo}/contents/${path50}?ref=${branch}`;
|
|
454928
|
-
const response = await fetch(url2, {
|
|
454929
|
-
headers: {
|
|
454930
|
-
Accept: "application/vnd.github.v3+json",
|
|
454931
|
-
"User-Agent": "letta-code"
|
|
454932
|
-
}
|
|
454933
|
-
});
|
|
454934
|
-
if (!response.ok) {
|
|
454935
|
-
throw new Error(`Failed to fetch from ${owner}/${repo}/${branch}/${path50}: ${response.statusText}`);
|
|
454936
|
-
}
|
|
454937
|
-
return await response.json();
|
|
454938
|
-
}
|
|
454939
|
-
function parseDirNames(entries) {
|
|
454940
|
-
return new Set(entries.filter((e2) => e2.type === "dir").map((e2) => e2.name));
|
|
454941
|
-
}
|
|
454942
|
-
|
|
454943
|
-
// src/agent/import.ts
|
|
454944
|
-
var exports_import = {};
|
|
454945
|
-
__export(exports_import, {
|
|
454946
|
-
importAgentFromRegistry: () => importAgentFromRegistry,
|
|
454947
|
-
importAgentFromFile: () => importAgentFromFile,
|
|
454948
|
-
extractSkillsFromAf: () => extractSkillsFromAf
|
|
454949
|
-
});
|
|
454950
|
-
import { createReadStream as createReadStream3 } from "node:fs";
|
|
454951
|
-
import { access as access3, chmod, mkdir as mkdir17, readFile as readFile30, writeFile as writeFile19 } from "node:fs/promises";
|
|
454952
|
-
import { dirname as dirname35, isAbsolute as isAbsolute31, relative as relative14, resolve as resolve40, sep as sep9, win32 as win325 } from "node:path";
|
|
454953
|
-
function validateImportedSkillName(name) {
|
|
454954
|
-
const trimmedName = name.trim();
|
|
454955
|
-
if (trimmedName !== name || trimmedName.length === 0 || trimmedName.length > MAX_SKILL_NAME_LENGTH || trimmedName === "." || trimmedName === ".." || !IMPORTED_SKILL_NAME_PATTERN.test(trimmedName)) {
|
|
454956
|
-
throw new Error(`Invalid imported skill name "${String(name)}". Skill names may only contain letters, numbers, dots, underscores, and hyphens.`);
|
|
454957
|
-
}
|
|
454958
|
-
return trimmedName;
|
|
454959
|
-
}
|
|
454960
|
-
function assertPathInside(parent, child) {
|
|
454961
|
-
const parentPath = resolve40(parent);
|
|
454962
|
-
const childPath = resolve40(child);
|
|
454963
|
-
const relativePath = relative14(parentPath, childPath);
|
|
454964
|
-
if (relativePath === "" || relativePath === ".." || relativePath.startsWith(`..${sep9}`) || isAbsolute31(relativePath)) {
|
|
454965
|
-
throw new Error(`Imported skill file path escapes skill directory: ${child}`);
|
|
454966
|
-
}
|
|
454967
|
-
}
|
|
454968
|
-
function validateImportedSkillFilePath(filePath) {
|
|
454969
|
-
if (filePath.length === 0 || filePath === "." || filePath.includes("\x00") || filePath.includes("\\") || isAbsolute31(filePath) || win325.isAbsolute(filePath)) {
|
|
454970
|
-
throw new Error(`Invalid imported skill file path "${filePath}".`);
|
|
454971
|
-
}
|
|
454972
|
-
const segments = filePath.split("/");
|
|
454973
|
-
if (segments.some((segment) => !segment || segment === "." || segment === "..")) {
|
|
454974
|
-
throw new Error(`Invalid imported skill file path "${filePath}".`);
|
|
454975
|
-
}
|
|
454976
|
-
return filePath;
|
|
454977
|
-
}
|
|
454978
|
-
function resolveImportedSkillFilePath(skillDir, filePath) {
|
|
454979
|
-
const safeFilePath = validateImportedSkillFilePath(filePath);
|
|
454980
|
-
const fullPath = resolve40(skillDir, safeFilePath);
|
|
454981
|
-
assertPathInside(skillDir, fullPath);
|
|
454982
|
-
return fullPath;
|
|
454983
|
-
}
|
|
454984
|
-
function tagsEqual(left, right) {
|
|
454985
|
-
return left.length === right.length && left.every((tag, i4) => tag === right[i4]);
|
|
454986
|
-
}
|
|
454987
|
-
async function resolveImportedAgentMemfsEnabled() {
|
|
454988
|
-
const backend3 = getBackend();
|
|
454989
|
-
const isLettaCloud2 = backend3.capabilities.remoteMemfs && !backend3.capabilities.localMemfs ? await Promise.resolve().then(() => (init_memory_filesystem2(), exports_memory_filesystem)).then((module3) => module3.isLettaCloud()) : false;
|
|
454990
|
-
return resolveCreatedAgentMemfsConfig({
|
|
454991
|
-
capabilities: backend3.capabilities,
|
|
454992
|
-
isLettaCloud: isLettaCloud2
|
|
454993
|
-
}).enableMemfs;
|
|
454994
|
-
}
|
|
454995
|
-
async function ensureImportedAgentCreationTags(agent, enableMemfs) {
|
|
454996
|
-
const tags = buildCreatedAgentTags({
|
|
454997
|
-
tags: agent.tags,
|
|
454998
|
-
enableMemfs
|
|
454999
|
-
});
|
|
455000
|
-
if (tagsEqual(agent.tags ?? [], tags)) {
|
|
455001
|
-
return agent;
|
|
455002
|
-
}
|
|
455003
|
-
const updatedAgent = await getBackend().updateAgent(agent.id, { tags });
|
|
455004
|
-
return {
|
|
455005
|
-
...agent,
|
|
455006
|
-
...updatedAgent,
|
|
455007
|
-
tags: updatedAgent.tags ?? tags
|
|
455008
|
-
};
|
|
455009
|
-
}
|
|
455010
|
-
async function importAgentFromFile(options) {
|
|
455011
|
-
if (!getBackend().capabilities.agentFileImportExport) {
|
|
455012
|
-
throw new Error("Agent file import is not supported by this backend yet");
|
|
455013
|
-
}
|
|
455014
|
-
const resolvedPath = resolve40(options.filePath);
|
|
455015
|
-
try {
|
|
455016
|
-
await access3(resolvedPath);
|
|
455017
|
-
} catch {
|
|
455018
|
-
throw new Error(`AgentFile not found: ${resolvedPath}`);
|
|
455019
|
-
}
|
|
455020
|
-
const client = await getClient();
|
|
455021
|
-
const file = createReadStream3(resolvedPath);
|
|
455022
|
-
const importResponse = await client.agents.importFile({
|
|
455023
|
-
file,
|
|
455024
|
-
strip_messages: options.stripMessages ?? true,
|
|
455025
|
-
override_existing_tools: false
|
|
455026
|
-
});
|
|
455027
|
-
if (!importResponse.agent_ids || importResponse.agent_ids.length === 0) {
|
|
455028
|
-
throw new Error("Import failed: no agent IDs returned");
|
|
455029
|
-
}
|
|
455030
|
-
const agentId = importResponse.agent_ids[0];
|
|
455031
|
-
let agent = await client.agents.retrieve(agentId, {
|
|
455032
|
-
include: ["agent.tags"]
|
|
455033
|
-
});
|
|
455034
|
-
if (options.modelOverride) {
|
|
455035
|
-
const updateArgs = getModelUpdateArgs(options.modelOverride);
|
|
455036
|
-
await updateAgentLLMConfig(agentId, options.modelOverride, updateArgs);
|
|
455037
|
-
const { ensureCorrectMemoryTool: ensureCorrectMemoryTool2 } = await init_toolset().then(() => exports_toolset);
|
|
455038
|
-
await ensureCorrectMemoryTool2(agentId, options.modelOverride);
|
|
455039
|
-
agent = await client.agents.retrieve(agentId, { include: ["agent.tags"] });
|
|
455040
|
-
}
|
|
455041
|
-
agent = await ensureImportedAgentCreationTags(agent, await resolveImportedAgentMemfsEnabled());
|
|
455042
|
-
let skills;
|
|
455043
|
-
if (!options.stripSkills) {
|
|
455044
|
-
const { getAgentSkillsDir: getAgentSkillsDir2 } = await Promise.resolve().then(() => (init_skills5(), exports_skills2));
|
|
455045
|
-
const skillsDir = getAgentSkillsDir2(agentId);
|
|
455046
|
-
skills = await extractSkillsFromAf(resolvedPath, skillsDir);
|
|
455047
|
-
}
|
|
455048
|
-
return { agent, skills };
|
|
455049
|
-
}
|
|
455050
|
-
async function extractSkillsFromAf(afPath, destDir) {
|
|
455051
|
-
const extracted = [];
|
|
455052
|
-
const content = await readFile30(afPath, "utf-8");
|
|
455053
|
-
const afData = JSON.parse(content);
|
|
455054
|
-
if (!afData.skills || !Array.isArray(afData.skills)) {
|
|
455055
|
-
return [];
|
|
455056
|
-
}
|
|
455057
|
-
for (const skill2 of afData.skills) {
|
|
455058
|
-
const skillName = validateImportedSkillName(skill2.name);
|
|
455059
|
-
const skillDir = resolve40(destDir, skillName);
|
|
455060
|
-
await mkdir17(skillDir, { recursive: true });
|
|
455061
|
-
if (skill2.files) {
|
|
455062
|
-
await writeSkillFiles(skillDir, skill2.files);
|
|
455063
|
-
extracted.push(skillName);
|
|
455064
|
-
} else if (skill2.source_url) {
|
|
455065
|
-
await fetchSkillFromUrl(skillDir, skill2.source_url);
|
|
455066
|
-
extracted.push(skillName);
|
|
455067
|
-
} else {
|
|
455068
|
-
console.warn(`Skipping skill ${skillName}: no files or source_url`);
|
|
455069
|
-
}
|
|
455070
|
-
}
|
|
455071
|
-
return extracted;
|
|
455072
|
-
}
|
|
455073
|
-
async function writeSkillFiles(skillDir, files) {
|
|
455074
|
-
for (const [filePath, fileContent] of Object.entries(files)) {
|
|
455075
|
-
await writeSkillFile(skillDir, filePath, fileContent);
|
|
455076
|
-
}
|
|
455077
|
-
}
|
|
455078
|
-
async function writeSkillFile(skillDir, filePath, content) {
|
|
455079
|
-
const fullPath = resolveImportedSkillFilePath(skillDir, filePath);
|
|
455080
|
-
await mkdir17(dirname35(fullPath), { recursive: true });
|
|
455081
|
-
await writeFile19(fullPath, content, "utf-8");
|
|
455082
|
-
const isScript = filePath.startsWith("scripts/") || content.trimStart().startsWith("#!");
|
|
455083
|
-
if (isScript) {
|
|
455084
|
-
try {
|
|
455085
|
-
await chmod(fullPath, 493);
|
|
455086
|
-
} catch {}
|
|
455087
|
-
}
|
|
455088
|
-
}
|
|
455089
|
-
async function fetchSkillFromUrl(skillDir, sourceUrl) {
|
|
455090
|
-
const githubPath = sourceUrl.replace(/^github\.com\//, "").replace(/\/tree\//, "/");
|
|
455091
|
-
const parts = githubPath.split("/");
|
|
455092
|
-
if (parts.length < 4 || !parts[0] || !parts[1] || !parts[2]) {
|
|
455093
|
-
throw new Error(`Invalid GitHub path: ${githubPath}`);
|
|
455094
|
-
}
|
|
455095
|
-
const owner = parts[0];
|
|
455096
|
-
const repo = parts[1];
|
|
455097
|
-
const branch = parts[2];
|
|
455098
|
-
const path50 = parts.slice(3).join("/");
|
|
455099
|
-
const { fetchGitHubContents: fetchGitHubContents2 } = await Promise.resolve().then(() => exports_github_utils);
|
|
455100
|
-
const entries = await fetchGitHubContents2(owner, repo, branch, path50);
|
|
455101
|
-
if (!Array.isArray(entries)) {
|
|
455102
|
-
throw new Error(`Expected directory at ${sourceUrl}, got file`);
|
|
455103
|
-
}
|
|
455104
|
-
await downloadGitHubDirectory(entries, skillDir, owner, repo, branch, path50);
|
|
455105
|
-
}
|
|
455106
|
-
async function downloadGitHubDirectory(entries, destDir, owner, repo, branch, basePath) {
|
|
455107
|
-
const { fetchGitHubContents: fetchGitHubContents2 } = await Promise.resolve().then(() => exports_github_utils);
|
|
455108
|
-
for (const entry of entries) {
|
|
455109
|
-
if (entry.type === "file") {
|
|
455110
|
-
if (!entry.download_url) {
|
|
455111
|
-
throw new Error(`Missing download_url for file: ${entry.path}`);
|
|
455112
|
-
}
|
|
455113
|
-
const fileResponse = await fetch(entry.download_url);
|
|
455114
|
-
const fileContent = await fileResponse.text();
|
|
455115
|
-
const relativePath = entry.path.replace(`${basePath}/`, "");
|
|
455116
|
-
await writeSkillFile(destDir, relativePath, fileContent);
|
|
455117
|
-
} else if (entry.type === "dir") {
|
|
455118
|
-
const subEntries = await fetchGitHubContents2(owner, repo, branch, entry.path);
|
|
455119
|
-
await downloadGitHubDirectory(subEntries, destDir, owner, repo, branch, basePath);
|
|
455120
|
-
}
|
|
455121
|
-
}
|
|
455122
|
-
}
|
|
455123
|
-
function parseRegistryHandle(handle2) {
|
|
455124
|
-
const normalized = handle2.startsWith("@") ? handle2.slice(1) : handle2;
|
|
455125
|
-
const parts = normalized.split("/");
|
|
455126
|
-
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
|
455127
|
-
throw new Error(`Invalid import handle "${handle2}". Use format: @author/agentname`);
|
|
455128
|
-
}
|
|
455129
|
-
return { author: parts[0], name: parts[1] };
|
|
455130
|
-
}
|
|
455131
|
-
async function importAgentFromRegistry(options) {
|
|
455132
|
-
const { tmpdir: tmpdir12 } = await import("node:os");
|
|
455133
|
-
const { join: join84 } = await import("node:path");
|
|
455134
|
-
const { writeFile: writeFile20, unlink: unlink6 } = await import("node:fs/promises");
|
|
455135
|
-
const { author, name } = parseRegistryHandle(options.handle);
|
|
455136
|
-
const rawUrl = `https://raw.githubusercontent.com/${AGENT_REGISTRY_OWNER}/${AGENT_REGISTRY_REPO}/refs/heads/${AGENT_REGISTRY_BRANCH}/agents/@${author}/${name}/${name}.af`;
|
|
455137
|
-
const response = await fetch(rawUrl);
|
|
455138
|
-
if (!response.ok) {
|
|
455139
|
-
if (response.status === 404) {
|
|
455140
|
-
throw new Error(`Agent @${author}/${name} not found in registry. Check that the agent exists at https://github.com/${AGENT_REGISTRY_OWNER}/${AGENT_REGISTRY_REPO}/tree/${AGENT_REGISTRY_BRANCH}/agents/@${author}/${name}`);
|
|
455141
|
-
}
|
|
455142
|
-
throw new Error(`Failed to download agent @${author}/${name}: ${response.statusText}`);
|
|
455143
|
-
}
|
|
455144
|
-
const afContent = await response.text();
|
|
455145
|
-
const tempPath = join84(tmpdir12(), `letta-import-${author}-${name}-${Date.now()}.af`);
|
|
455146
|
-
await writeFile20(tempPath, afContent, "utf-8");
|
|
455147
|
-
try {
|
|
455148
|
-
const result2 = await importAgentFromFile({
|
|
455149
|
-
filePath: tempPath,
|
|
455150
|
-
modelOverride: options.modelOverride,
|
|
455151
|
-
stripMessages: options.stripMessages ?? true,
|
|
455152
|
-
stripSkills: options.stripSkills ?? false
|
|
455153
|
-
});
|
|
455154
|
-
return result2;
|
|
455155
|
-
} finally {
|
|
455156
|
-
try {
|
|
455157
|
-
await unlink6(tempPath);
|
|
455158
|
-
} catch {}
|
|
455159
|
-
}
|
|
455160
|
-
}
|
|
455161
|
-
var IMPORTED_SKILL_NAME_PATTERN, AGENT_REGISTRY_OWNER = "letta-ai", AGENT_REGISTRY_REPO = "agent-file", AGENT_REGISTRY_BRANCH = "main";
|
|
455162
|
-
var init_import = __esm(() => {
|
|
455163
|
-
init_backend2();
|
|
455164
|
-
init_client4();
|
|
455165
|
-
init_validate_skill();
|
|
455166
|
-
init_create5();
|
|
455167
|
-
init_model();
|
|
455168
|
-
init_modify();
|
|
455169
|
-
IMPORTED_SKILL_NAME_PATTERN = /^[A-Za-z0-9._-]+$/;
|
|
455170
|
-
});
|
|
455171
|
-
|
|
455172
455025
|
// src/agent/defaults.ts
|
|
455173
455026
|
var exports_defaults = {};
|
|
455174
455027
|
__export(exports_defaults, {
|
|
@@ -455533,10 +455386,10 @@ async function sendScopedApprovalMessages(params) {
|
|
|
455533
455386
|
});
|
|
455534
455387
|
}
|
|
455535
455388
|
async function flushAndExit(code2) {
|
|
455536
|
-
const flushWritable = (stream12) => new Promise((
|
|
455389
|
+
const flushWritable = (stream12) => new Promise((resolve39) => {
|
|
455537
455390
|
if (stream12.destroyed || stream12.writableEnded)
|
|
455538
|
-
return
|
|
455539
|
-
stream12.write("", () =>
|
|
455391
|
+
return resolve39();
|
|
455392
|
+
stream12.write("", () => resolve39());
|
|
455540
455393
|
});
|
|
455541
455394
|
await closeClientMcpServers();
|
|
455542
455395
|
await Promise.allSettled([
|
|
@@ -455546,12 +455399,12 @@ async function flushAndExit(code2) {
|
|
|
455546
455399
|
process.exit(code2);
|
|
455547
455400
|
}
|
|
455548
455401
|
async function writeFinalHeadlessStdout(text2) {
|
|
455549
|
-
await new Promise((
|
|
455402
|
+
await new Promise((resolve39) => {
|
|
455550
455403
|
if (process.stdout.destroyed || process.stdout.writableEnded) {
|
|
455551
|
-
|
|
455404
|
+
resolve39();
|
|
455552
455405
|
return;
|
|
455553
455406
|
}
|
|
455554
|
-
process.stdout.write(text2, () =>
|
|
455407
|
+
process.stdout.write(text2, () => resolve39());
|
|
455555
455408
|
});
|
|
455556
455409
|
}
|
|
455557
455410
|
function buildEnvironmentResponseMetadata(params) {
|
|
@@ -455698,10 +455551,6 @@ In headless mode, use:
|
|
|
455698
455551
|
process.exit(1);
|
|
455699
455552
|
}
|
|
455700
455553
|
const shouldAutoEnableMemfsForNewAgent = !memfsFlag && !isStatelessSession;
|
|
455701
|
-
const fromAfFile = resolveImportFlagAlias({
|
|
455702
|
-
importFlagValue: values4.import,
|
|
455703
|
-
fromAfFlagValue: values4["from-af"]
|
|
455704
|
-
});
|
|
455705
455554
|
const preLoadSkillsRaw = values4["pre-load-skills"];
|
|
455706
455555
|
const systemInfoReminderEnabled = systemInfoReminderEnabledOverride ?? !values4["no-system-info-reminder"];
|
|
455707
455556
|
const reflectionOverrides = (() => {
|
|
@@ -455754,7 +455603,7 @@ In headless mode, use:
|
|
|
455754
455603
|
return reportAndExitHeadless("headless_conversation_shorthand_failed", error5, "headless_startup_conversation_shorthand");
|
|
455755
455604
|
}
|
|
455756
455605
|
const ambientAgentId = (process.env.LETTA_AGENT_ID || process.env.AGENT_ID || "").trim();
|
|
455757
|
-
if ((startupOptions.requestedBackendMode || usesRemoteEnvironment) && ambientAgentId && !specifiedAgentId && !specifiedAgentName && !specifiedConversationId && !forceNew && !
|
|
455606
|
+
if ((startupOptions.requestedBackendMode || usesRemoteEnvironment) && ambientAgentId && !specifiedAgentId && !specifiedAgentName && !specifiedConversationId && !forceNew && !fromAgentId) {
|
|
455758
455607
|
specifiedAgentId = ambientAgentId;
|
|
455759
455608
|
specifiedAgentIdFromAmbient = true;
|
|
455760
455609
|
}
|
|
@@ -455791,7 +455640,6 @@ In headless mode, use:
|
|
|
455791
455640
|
specifiedAgentName,
|
|
455792
455641
|
forceNewAgent: forceNew,
|
|
455793
455642
|
forceNewConversation,
|
|
455794
|
-
importFile: fromAfFile,
|
|
455795
455643
|
stateless: statelessFlag,
|
|
455796
455644
|
ephemeral: ephemeralFlag,
|
|
455797
455645
|
isHeadless: true,
|
|
@@ -455804,39 +455652,6 @@ In headless mode, use:
|
|
|
455804
455652
|
if (ephemeralFlag && (isBidirectionalMode || usesRemoteEnvironment)) {
|
|
455805
455653
|
return reportAndExitHeadless("headless_ephemeral_transport_unsupported", "--ephemeral supports direct one-shot headless prompts only", "headless_startup_flag_conflicts");
|
|
455806
455654
|
}
|
|
455807
|
-
let isRegistryImport = false;
|
|
455808
|
-
if (fromAfFile) {
|
|
455809
|
-
try {
|
|
455810
|
-
validateFlagConflicts({
|
|
455811
|
-
guard: fromAfFile,
|
|
455812
|
-
checks: [
|
|
455813
|
-
{
|
|
455814
|
-
when: specifiedAgentId,
|
|
455815
|
-
message: "--import cannot be used with --agent"
|
|
455816
|
-
},
|
|
455817
|
-
{
|
|
455818
|
-
when: specifiedAgentName,
|
|
455819
|
-
message: "--import cannot be used with --name"
|
|
455820
|
-
},
|
|
455821
|
-
{
|
|
455822
|
-
when: forceNew,
|
|
455823
|
-
message: "--import cannot be used with --new-agent"
|
|
455824
|
-
}
|
|
455825
|
-
]
|
|
455826
|
-
});
|
|
455827
|
-
} catch (error5) {
|
|
455828
|
-
return reportAndExitHeadless("headless_import_flag_validation_failed", error5, "headless_startup_import_flag_validation");
|
|
455829
|
-
}
|
|
455830
|
-
if (fromAfFile.startsWith("@")) {
|
|
455831
|
-
isRegistryImport = true;
|
|
455832
|
-
try {
|
|
455833
|
-
validateRegistryHandleOrThrow(fromAfFile);
|
|
455834
|
-
} catch {
|
|
455835
|
-
console.error(`Error: Invalid registry handle "${fromAfFile}". Use format: letta --import @author/agentname`);
|
|
455836
|
-
process.exit(1);
|
|
455837
|
-
}
|
|
455838
|
-
}
|
|
455839
|
-
}
|
|
455840
455655
|
if (specifiedAgentName) {
|
|
455841
455656
|
if (specifiedAgentId) {
|
|
455842
455657
|
console.error("Error: --name cannot be used with --agent");
|
|
@@ -455878,35 +455693,6 @@ In headless mode, use:
|
|
|
455878
455693
|
process.exit(1);
|
|
455879
455694
|
}
|
|
455880
455695
|
}
|
|
455881
|
-
if (!agent && fromAfFile) {
|
|
455882
|
-
let result2;
|
|
455883
|
-
if (isRegistryImport) {
|
|
455884
|
-
const { importAgentFromRegistry: importAgentFromRegistry2 } = await Promise.resolve().then(() => (init_import(), exports_import));
|
|
455885
|
-
result2 = await importAgentFromRegistry2({
|
|
455886
|
-
handle: fromAfFile,
|
|
455887
|
-
modelOverride: model,
|
|
455888
|
-
stripMessages: true,
|
|
455889
|
-
stripSkills: false
|
|
455890
|
-
});
|
|
455891
|
-
} else {
|
|
455892
|
-
const { importAgentFromFile: importAgentFromFile2 } = await Promise.resolve().then(() => (init_import(), exports_import));
|
|
455893
|
-
result2 = await importAgentFromFile2({
|
|
455894
|
-
filePath: fromAfFile,
|
|
455895
|
-
modelOverride: model,
|
|
455896
|
-
stripMessages: true,
|
|
455897
|
-
stripSkills: false
|
|
455898
|
-
});
|
|
455899
|
-
}
|
|
455900
|
-
agent = result2.agent;
|
|
455901
|
-
if (settingsManager.isReady) {
|
|
455902
|
-
settingsManager.setSystemPromptCustom(agent.id);
|
|
455903
|
-
}
|
|
455904
|
-
if (result2.skills && result2.skills.length > 0) {
|
|
455905
|
-
const { getAgentSkillsDir: getAgentSkillsDir2 } = await Promise.resolve().then(() => (init_skills5(), exports_skills2));
|
|
455906
|
-
const skillsDir = getAgentSkillsDir2(agent.id);
|
|
455907
|
-
console.log(`\uD83D\uDCE6 Extracted ${result2.skills.length} skill${result2.skills.length === 1 ? "" : "s"} to ${skillsDir}: ${result2.skills.join(", ")}`);
|
|
455908
|
-
}
|
|
455909
|
-
}
|
|
455910
455696
|
if (!agent && specifiedAgentId) {
|
|
455911
455697
|
try {
|
|
455912
455698
|
agent = await backend3.retrieveAgent(specifiedAgentId, {
|
|
@@ -456023,7 +455809,7 @@ Current session AGENT_ID=${process.env.AGENT_ID}; --backend local switches to a
|
|
|
456023
455809
|
markMilestone("HEADLESS_AGENT_RESOLVED");
|
|
456024
455810
|
const publicAgentId = ephemeralFlag ? null : agent.id;
|
|
456025
455811
|
telemetry.setCurrentAgent(publicAgentId, agent.tags);
|
|
456026
|
-
const isResumingAgent = !ephemeralFlag && !!(specifiedAgentId || !forceNew
|
|
455812
|
+
const isResumingAgent = !ephemeralFlag && !!(specifiedAgentId || !forceNew);
|
|
456027
455813
|
if (isResumingAgent) {
|
|
456028
455814
|
if (model) {
|
|
456029
455815
|
const modelHandle = resolveModel(model);
|
|
@@ -456789,7 +456575,7 @@ ${loadedContents.join(`
|
|
|
456789
456575
|
} else {
|
|
456790
456576
|
console.error(`Conversation is busy, waiting ${Math.round(retryDelayMs / 1000)}s and retrying...`);
|
|
456791
456577
|
}
|
|
456792
|
-
await new Promise((
|
|
456578
|
+
await new Promise((resolve39) => setTimeout(resolve39, retryDelayMs));
|
|
456793
456579
|
continue;
|
|
456794
456580
|
}
|
|
456795
456581
|
}
|
|
@@ -456818,7 +456604,7 @@ ${loadedContents.join(`
|
|
|
456818
456604
|
const delaySeconds = Math.round(delayMs / 1000);
|
|
456819
456605
|
console.error(`Transient API error before streaming (attempt ${attempt2} of ${LLM_API_ERROR_MAX_RETRIES2}), retrying in ${delaySeconds}s...`);
|
|
456820
456606
|
}
|
|
456821
|
-
await new Promise((
|
|
456607
|
+
await new Promise((resolve39) => setTimeout(resolve39, delayMs));
|
|
456822
456608
|
conversationBusyRetries = 0;
|
|
456823
456609
|
continue;
|
|
456824
456610
|
}
|
|
@@ -457073,7 +456859,7 @@ ${loadedContents.join(`
|
|
|
457073
456859
|
const delaySeconds = Math.round(delayMs / 1000);
|
|
457074
456860
|
console.error(`LLM API error encountered (attempt ${attempt2} of ${LLM_API_ERROR_MAX_RETRIES2}), retrying in ${delaySeconds}s...`);
|
|
457075
456861
|
}
|
|
457076
|
-
await new Promise((
|
|
456862
|
+
await new Promise((resolve39) => setTimeout(resolve39, delayMs));
|
|
457077
456863
|
currentInput = refreshInputOtidsForNewRequest(currentInput);
|
|
457078
456864
|
continue;
|
|
457079
456865
|
}
|
|
@@ -457165,7 +456951,7 @@ ${loadedContents.join(`
|
|
|
457165
456951
|
} else {
|
|
457166
456952
|
console.error(`Empty LLM response, retrying (attempt ${attempt2} of ${EMPTY_RESPONSE_MAX_RETRIES2})...`);
|
|
457167
456953
|
}
|
|
457168
|
-
await new Promise((
|
|
456954
|
+
await new Promise((resolve39) => setTimeout(resolve39, delayMs));
|
|
457169
456955
|
currentInput = refreshInputOtidsForNewRequest(currentInput);
|
|
457170
456956
|
continue;
|
|
457171
456957
|
}
|
|
@@ -457193,7 +456979,7 @@ ${loadedContents.join(`
|
|
|
457193
456979
|
const delaySeconds = Math.round(delayMs / 1000);
|
|
457194
456980
|
console.error(`LLM API error encountered (attempt ${attempt2} of ${LLM_API_ERROR_MAX_RETRIES2}), retrying in ${delaySeconds}s...`);
|
|
457195
456981
|
}
|
|
457196
|
-
await new Promise((
|
|
456982
|
+
await new Promise((resolve39) => setTimeout(resolve39, delayMs));
|
|
457197
456983
|
currentInput = refreshInputOtidsForNewRequest(currentInput);
|
|
457198
456984
|
continue;
|
|
457199
456985
|
}
|
|
@@ -457223,7 +457009,7 @@ ${loadedContents.join(`
|
|
|
457223
457009
|
const delaySeconds = Math.round(delayMs / 1000);
|
|
457224
457010
|
console.error(`LLM API error encountered (attempt ${attempt2} of ${LLM_API_ERROR_MAX_RETRIES2}), retrying in ${delaySeconds}s...`);
|
|
457225
457011
|
}
|
|
457226
|
-
await new Promise((
|
|
457012
|
+
await new Promise((resolve39) => setTimeout(resolve39, delayMs));
|
|
457227
457013
|
currentInput = refreshInputOtidsForNewRequest(currentInput);
|
|
457228
457014
|
continue;
|
|
457229
457015
|
}
|
|
@@ -457618,9 +457404,9 @@ async function runBidirectionalMode(agent, conversationId, _outputFormat, includ
|
|
|
457618
457404
|
const syntheticUserLine = serializeQueuedMessageAsUserLine(queuedMessage);
|
|
457619
457405
|
maybeNotifyBlocked(syntheticUserLine);
|
|
457620
457406
|
if (lineResolver) {
|
|
457621
|
-
const
|
|
457407
|
+
const resolve39 = lineResolver;
|
|
457622
457408
|
lineResolver = null;
|
|
457623
|
-
|
|
457409
|
+
resolve39(syntheticUserLine);
|
|
457624
457410
|
return;
|
|
457625
457411
|
}
|
|
457626
457412
|
lineQueue.push(syntheticUserLine);
|
|
@@ -457640,9 +457426,9 @@ async function runBidirectionalMode(agent, conversationId, _outputFormat, includ
|
|
|
457640
457426
|
if (action3 === "abort-active") {
|
|
457641
457427
|
currentAbortController.abort();
|
|
457642
457428
|
if (lineResolver) {
|
|
457643
|
-
const
|
|
457429
|
+
const resolve39 = lineResolver;
|
|
457644
457430
|
lineResolver = null;
|
|
457645
|
-
|
|
457431
|
+
resolve39(null);
|
|
457646
457432
|
}
|
|
457647
457433
|
} else if (action3 === "latch") {
|
|
457648
457434
|
pendingInterrupt = true;
|
|
@@ -457662,9 +457448,9 @@ async function runBidirectionalMode(agent, conversationId, _outputFormat, includ
|
|
|
457662
457448
|
if (lineResolver) {
|
|
457663
457449
|
if (parsedLine?.type === "user")
|
|
457664
457450
|
turnStarting = true;
|
|
457665
|
-
const
|
|
457451
|
+
const resolve39 = lineResolver;
|
|
457666
457452
|
lineResolver = null;
|
|
457667
|
-
|
|
457453
|
+
resolve39(line);
|
|
457668
457454
|
} else {
|
|
457669
457455
|
lineQueue.push(line);
|
|
457670
457456
|
}
|
|
@@ -457673,17 +457459,17 @@ async function runBidirectionalMode(agent, conversationId, _outputFormat, includ
|
|
|
457673
457459
|
setMessageQueueAdder(null);
|
|
457674
457460
|
msgQueueRuntime.clear("shutdown");
|
|
457675
457461
|
if (lineResolver) {
|
|
457676
|
-
const
|
|
457462
|
+
const resolve39 = lineResolver;
|
|
457677
457463
|
lineResolver = null;
|
|
457678
|
-
|
|
457464
|
+
resolve39(null);
|
|
457679
457465
|
}
|
|
457680
457466
|
});
|
|
457681
457467
|
async function getNextLine() {
|
|
457682
457468
|
if (lineQueue.length > 0) {
|
|
457683
457469
|
return lineQueue.shift() ?? null;
|
|
457684
457470
|
}
|
|
457685
|
-
return new Promise((
|
|
457686
|
-
lineResolver =
|
|
457471
|
+
return new Promise((resolve39) => {
|
|
457472
|
+
lineResolver = resolve39;
|
|
457687
457473
|
});
|
|
457688
457474
|
}
|
|
457689
457475
|
async function requestPermission(toolCallId, toolName2, toolInput) {
|
|
@@ -458171,7 +457957,7 @@ async function runBidirectionalMode(agent, conversationId, _outputFormat, includ
|
|
|
458171
457957
|
uuid: `retry-bidir-${randomUUID37()}`
|
|
458172
457958
|
};
|
|
458173
457959
|
writeWireMessage(retryMsg);
|
|
458174
|
-
await new Promise((
|
|
457960
|
+
await new Promise((resolve39) => setTimeout(resolve39, delayMs));
|
|
458175
457961
|
continue;
|
|
458176
457962
|
}
|
|
458177
457963
|
throw preStreamError;
|
|
@@ -458885,7 +458671,7 @@ var BYTES_PER_TOKEN = 4;
|
|
|
458885
458671
|
|
|
458886
458672
|
// src/cli/helpers/window-title-config.ts
|
|
458887
458673
|
import { homedir as homedir45 } from "node:os";
|
|
458888
|
-
import { basename as
|
|
458674
|
+
import { basename as basename29, resolve as resolve39 } from "node:path";
|
|
458889
458675
|
function isWindowTitleField(value) {
|
|
458890
458676
|
return WINDOW_TITLE_FIELDS.includes(value);
|
|
458891
458677
|
}
|
|
@@ -459043,8 +458829,8 @@ function terminalTitleProjectName(data) {
|
|
|
459043
458829
|
const directory = titleDirectory(data);
|
|
459044
458830
|
if (!directory)
|
|
459045
458831
|
return null;
|
|
459046
|
-
const resolved =
|
|
459047
|
-
const name =
|
|
458832
|
+
const resolved = resolve39(directory);
|
|
458833
|
+
const name = basename29(resolved) || formatDirectoryDisplay(resolved) || resolved;
|
|
459048
458834
|
return truncateTerminalTitlePart(name, 24);
|
|
459049
458835
|
}
|
|
459050
458836
|
function titleDirectory(data) {
|
|
@@ -459053,7 +458839,7 @@ function titleDirectory(data) {
|
|
|
459053
458839
|
function formatDirectoryDisplay(directory) {
|
|
459054
458840
|
if (!directory)
|
|
459055
458841
|
return null;
|
|
459056
|
-
const resolved =
|
|
458842
|
+
const resolved = resolve39(directory);
|
|
459057
458843
|
const home = homedir45();
|
|
459058
458844
|
if (resolved === home)
|
|
459059
458845
|
return "~";
|
|
@@ -459776,10 +459562,10 @@ var init_queued_message_parts = __esm(() => {
|
|
|
459776
459562
|
|
|
459777
459563
|
// src/cli/helpers/reflection-arena-hf-upload.ts
|
|
459778
459564
|
import { execFile as execFileCb5 } from "node:child_process";
|
|
459779
|
-
import { existsSync as
|
|
459780
|
-
import { appendFile as appendFile2, chmod
|
|
459565
|
+
import { existsSync as existsSync66 } from "node:fs";
|
|
459566
|
+
import { appendFile as appendFile2, chmod, mkdir as mkdir17, writeFile as writeFile19 } from "node:fs/promises";
|
|
459781
459567
|
import { homedir as homedir46 } from "node:os";
|
|
459782
|
-
import { join as
|
|
459568
|
+
import { join as join84 } from "node:path";
|
|
459783
459569
|
import { promisify as promisify16 } from "node:util";
|
|
459784
459570
|
function buildGitEnv(token2, askpassPath) {
|
|
459785
459571
|
return {
|
|
@@ -459815,8 +459601,8 @@ async function runGit6(cwd2, args, env5) {
|
|
|
459815
459601
|
}
|
|
459816
459602
|
}
|
|
459817
459603
|
async function writeGitAskpass(repoRoot) {
|
|
459818
|
-
const askpassPath =
|
|
459819
|
-
await
|
|
459604
|
+
const askpassPath = join84(repoRoot, "hf-askpass.sh");
|
|
459605
|
+
await writeFile19(askpassPath, [
|
|
459820
459606
|
"#!/bin/sh",
|
|
459821
459607
|
'case "$1" in',
|
|
459822
459608
|
" *Username*) printf '%s\\n' 'hf_user' ;;",
|
|
@@ -459825,12 +459611,12 @@ async function writeGitAskpass(repoRoot) {
|
|
|
459825
459611
|
""
|
|
459826
459612
|
].join(`
|
|
459827
459613
|
`), { encoding: "utf-8", mode: 448 });
|
|
459828
|
-
await
|
|
459614
|
+
await chmod(askpassPath, 448);
|
|
459829
459615
|
return askpassPath;
|
|
459830
459616
|
}
|
|
459831
459617
|
async function prepareHfRepo(env5) {
|
|
459832
|
-
await
|
|
459833
|
-
if (!
|
|
459618
|
+
await mkdir17(HF_CACHE_ROOT, { recursive: true });
|
|
459619
|
+
if (!existsSync66(join84(HF_REPO_DIR, ".git"))) {
|
|
459834
459620
|
await runGit6(HF_CACHE_ROOT, ["clone", "--depth", "1", HF_REPO_URL, HF_REPO_DIR], env5);
|
|
459835
459621
|
return HF_REPO_DIR;
|
|
459836
459622
|
}
|
|
@@ -459860,13 +459646,13 @@ async function maybeUploadReflectionArenaChoiceToHf(row) {
|
|
|
459860
459646
|
if (!token2) {
|
|
459861
459647
|
return { uploaded: false, reason: "missing_token" };
|
|
459862
459648
|
}
|
|
459863
|
-
await
|
|
459649
|
+
await mkdir17(HF_CACHE_ROOT, { recursive: true });
|
|
459864
459650
|
const askpassPath = await writeGitAskpass(HF_CACHE_ROOT);
|
|
459865
459651
|
const env5 = buildGitEnv(token2, askpassPath);
|
|
459866
459652
|
try {
|
|
459867
459653
|
const repoDir = await prepareHfRepo(env5);
|
|
459868
|
-
await
|
|
459869
|
-
await appendFile2(
|
|
459654
|
+
await mkdir17(join84(repoDir, "data"), { recursive: true });
|
|
459655
|
+
await appendFile2(join84(repoDir, HF_DATASET_PATH), `${JSON.stringify(row)}
|
|
459870
459656
|
`, {
|
|
459871
459657
|
encoding: "utf-8"
|
|
459872
459658
|
});
|
|
@@ -459894,16 +459680,16 @@ var init_reflection_arena_hf_upload = __esm(() => {
|
|
|
459894
459680
|
init_version();
|
|
459895
459681
|
execFile18 = promisify16(execFileCb5);
|
|
459896
459682
|
HF_REPO_URL = `https://huggingface.co/datasets/${HF_REPO_ID}`;
|
|
459897
|
-
HF_CACHE_ROOT =
|
|
459898
|
-
HF_REPO_DIR =
|
|
459683
|
+
HF_CACHE_ROOT = join84(homedir46(), ".letta", "reflection-arena", "hf-upload");
|
|
459684
|
+
HF_REPO_DIR = join84(HF_CACHE_ROOT, "repo");
|
|
459899
459685
|
});
|
|
459900
459686
|
|
|
459901
459687
|
// src/cli/helpers/reflection-arena.ts
|
|
459902
459688
|
import { execFile as execFileCb6 } from "node:child_process";
|
|
459903
459689
|
import { randomInt as randomInt2, randomUUID as randomUUID38 } from "node:crypto";
|
|
459904
|
-
import { appendFile as appendFile3, mkdir as
|
|
459690
|
+
import { appendFile as appendFile3, mkdir as mkdir18, readFile as readFile30, writeFile as writeFile20 } from "node:fs/promises";
|
|
459905
459691
|
import { homedir as homedir47 } from "node:os";
|
|
459906
|
-
import { join as
|
|
459692
|
+
import { join as join85 } from "node:path";
|
|
459907
459693
|
import { promisify as promisify17 } from "node:util";
|
|
459908
459694
|
function sampleReflectionArenaComparisonModel(excludedModels = []) {
|
|
459909
459695
|
const excluded = new Set(excludedModels);
|
|
@@ -459952,24 +459738,24 @@ function candidateIsConfirmedNoOp(candidate) {
|
|
|
459952
459738
|
return candidate.result?.success === true && candidate.result.memoryNoChanges === true && candidate.result.memoryHead === candidate.worktree.baseHead;
|
|
459953
459739
|
}
|
|
459954
459740
|
function getReflectionArenaRoot() {
|
|
459955
|
-
return
|
|
459741
|
+
return join85(homedir47(), ".letta", "reflection-arena");
|
|
459956
459742
|
}
|
|
459957
459743
|
function getReflectionArenaRunsDir() {
|
|
459958
|
-
return
|
|
459744
|
+
return join85(getReflectionArenaRoot(), "runs");
|
|
459959
459745
|
}
|
|
459960
459746
|
function getReflectionArenaChoiceLogPath() {
|
|
459961
|
-
return
|
|
459747
|
+
return join85(getReflectionArenaRoot(), "choices.jsonl");
|
|
459962
459748
|
}
|
|
459963
459749
|
function getReflectionArenaRunPath(runId) {
|
|
459964
|
-
return
|
|
459750
|
+
return join85(getReflectionArenaRunsDir(), `${runId}.json`);
|
|
459965
459751
|
}
|
|
459966
459752
|
async function saveReflectionArenaRun(run) {
|
|
459967
|
-
await
|
|
459968
|
-
await
|
|
459753
|
+
await mkdir18(getReflectionArenaRunsDir(), { recursive: true });
|
|
459754
|
+
await writeFile20(getReflectionArenaRunPath(run.runId), `${JSON.stringify(run, null, 2)}
|
|
459969
459755
|
`, "utf-8");
|
|
459970
459756
|
}
|
|
459971
459757
|
async function loadReflectionArenaRun(runId) {
|
|
459972
|
-
const raw2 = await
|
|
459758
|
+
const raw2 = await readFile30(getReflectionArenaRunPath(runId), "utf-8");
|
|
459973
459759
|
return JSON.parse(raw2);
|
|
459974
459760
|
}
|
|
459975
459761
|
async function updateReflectionArenaRun(runId, update3) {
|
|
@@ -460135,7 +459921,7 @@ function formatReflectionArenaChoiceResult(params) {
|
|
|
460135
459921
|
`);
|
|
460136
459922
|
}
|
|
460137
459923
|
async function appendChoiceRecord(run) {
|
|
460138
|
-
await
|
|
459924
|
+
await mkdir18(getReflectionArenaRoot(), { recursive: true });
|
|
460139
459925
|
await appendFile3(getReflectionArenaChoiceLogPath(), `${JSON.stringify({
|
|
460140
459926
|
run_id: run.runId,
|
|
460141
459927
|
agent_id: run.agentId,
|
|
@@ -460161,7 +459947,7 @@ async function appendChoiceRecord(run) {
|
|
|
460161
459947
|
}
|
|
460162
459948
|
async function readTranscriptPayloadForTelemetry(payloadPath) {
|
|
460163
459949
|
try {
|
|
460164
|
-
const transcript = await
|
|
459950
|
+
const transcript = await readFile30(payloadPath, "utf-8");
|
|
460165
459951
|
return {
|
|
460166
459952
|
transcriptPayload: transcript.slice(0, REFLECTION_ARENA_TELEMETRY_TRANSCRIPT_MAX_CHARS),
|
|
460167
459953
|
transcriptPayloadChars: transcript.length,
|
|
@@ -460852,8 +460638,8 @@ async function pushToMemoryRepositoryWithTimeout(agentId) {
|
|
|
460852
460638
|
try {
|
|
460853
460639
|
return await Promise.race([
|
|
460854
460640
|
pushToMemoryRepository(agentId),
|
|
460855
|
-
new Promise((
|
|
460856
|
-
timeout = setTimeout(() =>
|
|
460641
|
+
new Promise((resolve40) => {
|
|
460642
|
+
timeout = setTimeout(() => resolve40("timeout"), INITIAL_PUSH_TIMEOUT_MS);
|
|
460857
460643
|
})
|
|
460858
460644
|
]);
|
|
460859
460645
|
} finally {
|
|
@@ -461117,13 +460903,13 @@ __export(exports_terminal_keybinding_installer, {
|
|
|
461117
460903
|
});
|
|
461118
460904
|
import {
|
|
461119
460905
|
copyFileSync as copyFileSync6,
|
|
461120
|
-
existsSync as
|
|
460906
|
+
existsSync as existsSync67,
|
|
461121
460907
|
mkdirSync as mkdirSync45,
|
|
461122
|
-
readFileSync as
|
|
460908
|
+
readFileSync as readFileSync42,
|
|
461123
460909
|
writeFileSync as writeFileSync35
|
|
461124
460910
|
} from "node:fs";
|
|
461125
460911
|
import { homedir as homedir48, platform as platform10 } from "node:os";
|
|
461126
|
-
import { dirname as
|
|
460912
|
+
import { dirname as dirname35, join as join86 } from "node:path";
|
|
461127
460913
|
function detectTerminalType() {
|
|
461128
460914
|
if (process.env.CURSOR_TRACE_ID || process.env.CURSOR_CHANNEL) {
|
|
461129
460915
|
return "cursor";
|
|
@@ -461155,16 +460941,16 @@ function getKeybindingsPath(terminal) {
|
|
|
461155
460941
|
}[terminal];
|
|
461156
460942
|
const os9 = platform10();
|
|
461157
460943
|
if (os9 === "darwin") {
|
|
461158
|
-
return
|
|
460944
|
+
return join86(homedir48(), "Library", "Application Support", appName, "User", "keybindings.json");
|
|
461159
460945
|
}
|
|
461160
460946
|
if (os9 === "win32") {
|
|
461161
460947
|
const appData = process.env.APPDATA;
|
|
461162
460948
|
if (!appData)
|
|
461163
460949
|
return null;
|
|
461164
|
-
return
|
|
460950
|
+
return join86(appData, appName, "User", "keybindings.json");
|
|
461165
460951
|
}
|
|
461166
460952
|
if (os9 === "linux") {
|
|
461167
|
-
return
|
|
460953
|
+
return join86(homedir48(), ".config", appName, "User", "keybindings.json");
|
|
461168
460954
|
}
|
|
461169
460955
|
return null;
|
|
461170
460956
|
}
|
|
@@ -461186,10 +460972,10 @@ function parseKeybindings(content) {
|
|
|
461186
460972
|
}
|
|
461187
460973
|
}
|
|
461188
460974
|
function keybindingExists(keybindingsPath) {
|
|
461189
|
-
if (!
|
|
460975
|
+
if (!existsSync67(keybindingsPath))
|
|
461190
460976
|
return false;
|
|
461191
460977
|
try {
|
|
461192
|
-
const content =
|
|
460978
|
+
const content = readFileSync42(keybindingsPath, { encoding: "utf-8" });
|
|
461193
460979
|
const keybindings = parseKeybindings(content);
|
|
461194
460980
|
if (!keybindings)
|
|
461195
460981
|
return false;
|
|
@@ -461199,7 +460985,7 @@ function keybindingExists(keybindingsPath) {
|
|
|
461199
460985
|
}
|
|
461200
460986
|
}
|
|
461201
460987
|
function createBackup(keybindingsPath) {
|
|
461202
|
-
if (!
|
|
460988
|
+
if (!existsSync67(keybindingsPath))
|
|
461203
460989
|
return null;
|
|
461204
460990
|
const backupPath = `${keybindingsPath}.letta-backup`;
|
|
461205
460991
|
try {
|
|
@@ -461214,15 +461000,15 @@ function installKeybinding(keybindingsPath) {
|
|
|
461214
461000
|
if (keybindingExists(keybindingsPath)) {
|
|
461215
461001
|
return { success: true, alreadyExists: true };
|
|
461216
461002
|
}
|
|
461217
|
-
const parentDir =
|
|
461218
|
-
if (!
|
|
461003
|
+
const parentDir = dirname35(keybindingsPath);
|
|
461004
|
+
if (!existsSync67(parentDir)) {
|
|
461219
461005
|
mkdirSync45(parentDir, { recursive: true });
|
|
461220
461006
|
}
|
|
461221
461007
|
let keybindings = [];
|
|
461222
461008
|
let backupPath = null;
|
|
461223
|
-
if (
|
|
461009
|
+
if (existsSync67(keybindingsPath)) {
|
|
461224
461010
|
backupPath = createBackup(keybindingsPath);
|
|
461225
|
-
const content =
|
|
461011
|
+
const content = readFileSync42(keybindingsPath, { encoding: "utf-8" });
|
|
461226
461012
|
const parsed = parseKeybindings(content);
|
|
461227
461013
|
if (parsed === null) {
|
|
461228
461014
|
return {
|
|
@@ -461250,10 +461036,10 @@ function installKeybinding(keybindingsPath) {
|
|
|
461250
461036
|
}
|
|
461251
461037
|
function removeKeybinding(keybindingsPath) {
|
|
461252
461038
|
try {
|
|
461253
|
-
if (!
|
|
461039
|
+
if (!existsSync67(keybindingsPath)) {
|
|
461254
461040
|
return { success: true };
|
|
461255
461041
|
}
|
|
461256
|
-
const content =
|
|
461042
|
+
const content = readFileSync42(keybindingsPath, { encoding: "utf-8" });
|
|
461257
461043
|
const keybindings = parseKeybindings(content);
|
|
461258
461044
|
if (!keybindings) {
|
|
461259
461045
|
return {
|
|
@@ -461317,14 +461103,14 @@ function getWezTermConfigPath() {
|
|
|
461317
461103
|
}
|
|
461318
461104
|
const xdgConfig = process.env.XDG_CONFIG_HOME;
|
|
461319
461105
|
if (xdgConfig) {
|
|
461320
|
-
const xdgPath =
|
|
461321
|
-
if (
|
|
461106
|
+
const xdgPath = join86(xdgConfig, "wezterm", "wezterm.lua");
|
|
461107
|
+
if (existsSync67(xdgPath))
|
|
461322
461108
|
return xdgPath;
|
|
461323
461109
|
}
|
|
461324
|
-
const configPath =
|
|
461325
|
-
if (
|
|
461110
|
+
const configPath = join86(homedir48(), ".config", "wezterm", "wezterm.lua");
|
|
461111
|
+
if (existsSync67(configPath))
|
|
461326
461112
|
return configPath;
|
|
461327
|
-
return
|
|
461113
|
+
return join86(homedir48(), ".wezterm.lua");
|
|
461328
461114
|
}
|
|
461329
461115
|
function stripLuaCommentsFromLine(line, blockCommentEnd) {
|
|
461330
461116
|
let code2 = "";
|
|
@@ -461427,10 +461213,10 @@ ${WEZTERM_DELETE_FIX}
|
|
|
461427
461213
|
`;
|
|
461428
461214
|
}
|
|
461429
461215
|
function wezTermDeleteFixExists(configPath) {
|
|
461430
|
-
if (!
|
|
461216
|
+
if (!existsSync67(configPath))
|
|
461431
461217
|
return false;
|
|
461432
461218
|
try {
|
|
461433
|
-
const content =
|
|
461219
|
+
const content = readFileSync42(configPath, { encoding: "utf-8" });
|
|
461434
461220
|
return content.includes("Letta Code: Fix Delete key") || content.includes("key = 'Delete'") && content.includes("SendString") && content.includes("\\x1b[3~");
|
|
461435
461221
|
} catch {
|
|
461436
461222
|
return false;
|
|
@@ -461444,14 +461230,14 @@ function installWezTermDeleteFix() {
|
|
|
461444
461230
|
}
|
|
461445
461231
|
let content = "";
|
|
461446
461232
|
let backupPath = null;
|
|
461447
|
-
if (
|
|
461233
|
+
if (existsSync67(configPath)) {
|
|
461448
461234
|
backupPath = `${configPath}.letta-backup`;
|
|
461449
461235
|
copyFileSync6(configPath, backupPath);
|
|
461450
|
-
content =
|
|
461236
|
+
content = readFileSync42(configPath, { encoding: "utf-8" });
|
|
461451
461237
|
}
|
|
461452
461238
|
content = injectWezTermDeleteFix(content);
|
|
461453
|
-
const parentDir =
|
|
461454
|
-
if (!
|
|
461239
|
+
const parentDir = dirname35(configPath);
|
|
461240
|
+
if (!existsSync67(parentDir)) {
|
|
461455
461241
|
mkdirSync45(parentDir, { recursive: true });
|
|
461456
461242
|
}
|
|
461457
461243
|
writeFileSync35(configPath, content, { encoding: "utf-8" });
|
|
@@ -461503,9 +461289,9 @@ __export(exports_settings2, {
|
|
|
461503
461289
|
getSetting: () => getSetting
|
|
461504
461290
|
});
|
|
461505
461291
|
import { homedir as homedir49 } from "node:os";
|
|
461506
|
-
import { join as
|
|
461292
|
+
import { join as join87 } from "node:path";
|
|
461507
461293
|
function getSettingsPath() {
|
|
461508
|
-
return
|
|
461294
|
+
return join87(homedir49(), ".letta", "settings.json");
|
|
461509
461295
|
}
|
|
461510
461296
|
async function loadSettings() {
|
|
461511
461297
|
const settingsPath = getSettingsPath();
|
|
@@ -461542,7 +461328,7 @@ async function getSetting(key2) {
|
|
|
461542
461328
|
return settings3[key2];
|
|
461543
461329
|
}
|
|
461544
461330
|
function getProjectSettingsPath() {
|
|
461545
|
-
return
|
|
461331
|
+
return join87(process.cwd(), ".letta", "settings.local.json");
|
|
461546
461332
|
}
|
|
461547
461333
|
async function loadProjectSettings() {
|
|
461548
461334
|
const settingsPath = getProjectSettingsPath();
|
|
@@ -461560,7 +461346,7 @@ async function loadProjectSettings() {
|
|
|
461560
461346
|
}
|
|
461561
461347
|
async function saveProjectSettings(settings3) {
|
|
461562
461348
|
const settingsPath = getProjectSettingsPath();
|
|
461563
|
-
const dirPath =
|
|
461349
|
+
const dirPath = join87(process.cwd(), ".letta");
|
|
461564
461350
|
try {
|
|
461565
461351
|
if (!exists(dirPath)) {
|
|
461566
461352
|
await mkdir(dirPath, { recursive: true });
|
|
@@ -461860,14 +461646,6 @@ var init_registry2 = __esm(() => {
|
|
|
461860
461646
|
return "Updating description...";
|
|
461861
461647
|
}
|
|
461862
461648
|
},
|
|
461863
|
-
"/export": {
|
|
461864
|
-
desc: "Export AgentFile (.af)",
|
|
461865
|
-
order: 26,
|
|
461866
|
-
noArgs: true,
|
|
461867
|
-
handler: () => {
|
|
461868
|
-
return "Exporting agent file...";
|
|
461869
|
-
}
|
|
461870
|
-
},
|
|
461871
461649
|
"/toolset": {
|
|
461872
461650
|
desc: "Switch toolset (replaces /link and /unlink)",
|
|
461873
461651
|
order: 27,
|
|
@@ -462185,14 +461963,6 @@ Location: ${keybindingsPath}`;
|
|
|
462185
461963
|
handler: () => {
|
|
462186
461964
|
return "Opening agent browser...";
|
|
462187
461965
|
}
|
|
462188
|
-
},
|
|
462189
|
-
"/download": {
|
|
462190
|
-
desc: "Export AgentFile (.af)",
|
|
462191
|
-
hidden: true,
|
|
462192
|
-
noArgs: true,
|
|
462193
|
-
handler: () => {
|
|
462194
|
-
return "Exporting agent file...";
|
|
462195
|
-
}
|
|
462196
461966
|
}
|
|
462197
461967
|
};
|
|
462198
461968
|
});
|
|
@@ -462608,10 +462378,10 @@ var init_InlineBashApproval = __esm(async () => {
|
|
|
462608
462378
|
});
|
|
462609
462379
|
|
|
462610
462380
|
// src/cli/components/DiffRenderer.tsx
|
|
462611
|
-
import { relative as
|
|
462381
|
+
import { relative as relative14 } from "node:path";
|
|
462612
462382
|
function formatDisplayPath4(filePath) {
|
|
462613
462383
|
const cwd2 = process.cwd();
|
|
462614
|
-
const relativePath =
|
|
462384
|
+
const relativePath = relative14(cwd2, filePath);
|
|
462615
462385
|
if (relativePath.startsWith("..")) {
|
|
462616
462386
|
return filePath;
|
|
462617
462387
|
}
|
|
@@ -462970,10 +462740,10 @@ var init_DiffRenderer = __esm(async () => {
|
|
|
462970
462740
|
});
|
|
462971
462741
|
|
|
462972
462742
|
// src/cli/components/AdvancedDiffRenderer.tsx
|
|
462973
|
-
import { relative as
|
|
462743
|
+
import { relative as relative15 } from "node:path";
|
|
462974
462744
|
function formatRelativePath(filePath) {
|
|
462975
462745
|
const cwd2 = process.cwd();
|
|
462976
|
-
const relativePath =
|
|
462746
|
+
const relativePath = relative15(cwd2, filePath);
|
|
462977
462747
|
return relativePath.startsWith("..") ? relativePath : `./${relativePath}`;
|
|
462978
462748
|
}
|
|
462979
462749
|
function padLeft(n, width) {
|
|
@@ -463255,7 +463025,7 @@ function AdvancedDiffRenderer(props) {
|
|
|
463255
463025
|
}
|
|
463256
463026
|
const { hunks } = result2;
|
|
463257
463027
|
const filePath = props.filePath;
|
|
463258
|
-
const
|
|
463028
|
+
const relative16 = formatRelativePath(filePath);
|
|
463259
463029
|
const lang41 = languageFromPath(filePath);
|
|
463260
463030
|
const shouldHighlight = lang41 && !exceedsAdvancedDiffHighlightLimits(hunks);
|
|
463261
463031
|
const hunkSyntaxLines = [];
|
|
@@ -463278,7 +463048,7 @@ function AdvancedDiffRenderer(props) {
|
|
|
463278
463048
|
const rows = buildAdvancedDiffRows(hunks, hunkSyntaxLines);
|
|
463279
463049
|
const maxDisplayNo = rows.reduce((m4, r5) => Math.max(m4, r5.displayNo), 1);
|
|
463280
463050
|
const gutterWidth = String(maxDisplayNo).length;
|
|
463281
|
-
const header = props.kind === "write" ? `Wrote changes to ${
|
|
463051
|
+
const header = props.kind === "write" ? `Wrote changes to ${relative16}` : `Updated ${relative16}`;
|
|
463282
463052
|
if (rows.length === 0) {
|
|
463283
463053
|
const noChangesGutter = 4;
|
|
463284
463054
|
return /* @__PURE__ */ jsx_dev_runtime24.jsxDEV(Box_default, {
|
|
@@ -463329,7 +463099,7 @@ function AdvancedDiffRenderer(props) {
|
|
|
463329
463099
|
"No changes to ",
|
|
463330
463100
|
/* @__PURE__ */ jsx_dev_runtime24.jsxDEV(Text2, {
|
|
463331
463101
|
bold: true,
|
|
463332
|
-
children:
|
|
463102
|
+
children: relative16
|
|
463333
463103
|
}, undefined, false, undefined, this),
|
|
463334
463104
|
" (file content identical)"
|
|
463335
463105
|
]
|
|
@@ -463435,9 +463205,9 @@ function getHeaderText(fileEdit) {
|
|
|
463435
463205
|
} else if (operations.length === 1) {
|
|
463436
463206
|
const op = operations[0];
|
|
463437
463207
|
if (op) {
|
|
463438
|
-
const { relative:
|
|
463208
|
+
const { relative: relative17 } = __require("node:path");
|
|
463439
463209
|
const cwd3 = process.cwd();
|
|
463440
|
-
const relPath2 =
|
|
463210
|
+
const relPath2 = relative17(cwd3, op.path);
|
|
463441
463211
|
const displayPath2 = relPath2.startsWith("..") ? op.path : relPath2;
|
|
463442
463212
|
if (op.kind === "add") {
|
|
463443
463213
|
return `Write to ${displayPath2}?`;
|
|
@@ -463451,14 +463221,14 @@ function getHeaderText(fileEdit) {
|
|
|
463451
463221
|
}
|
|
463452
463222
|
return "Apply patch?";
|
|
463453
463223
|
}
|
|
463454
|
-
const { relative:
|
|
463224
|
+
const { relative: relative16 } = __require("node:path");
|
|
463455
463225
|
const cwd2 = process.cwd();
|
|
463456
|
-
const relPath =
|
|
463226
|
+
const relPath = relative16(cwd2, fileEdit.filePath);
|
|
463457
463227
|
const displayPath = relPath.startsWith("..") ? fileEdit.filePath : relPath;
|
|
463458
463228
|
if (t2 === "write" || t2 === "write_file" || t2 === "writefile" || t2 === "write_file_gemini" || t2 === "writefilegemini") {
|
|
463459
|
-
const { existsSync:
|
|
463229
|
+
const { existsSync: existsSync68 } = __require("node:fs");
|
|
463460
463230
|
try {
|
|
463461
|
-
if (
|
|
463231
|
+
if (existsSync68(fileEdit.filePath)) {
|
|
463462
463232
|
return `Overwrite ${displayPath}?`;
|
|
463463
463233
|
}
|
|
463464
463234
|
} catch {}
|
|
@@ -463636,9 +463406,9 @@ var init_InlineFileEditApproval = __esm(async () => {
|
|
|
463636
463406
|
children: fileEdit.patchInput ? /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Box_default, {
|
|
463637
463407
|
flexDirection: "column",
|
|
463638
463408
|
children: parsePatchOperations2(fileEdit.patchInput).map((op, idx) => {
|
|
463639
|
-
const { relative:
|
|
463409
|
+
const { relative: relative16 } = __require("node:path");
|
|
463640
463410
|
const cwd2 = process.cwd();
|
|
463641
|
-
const relPath =
|
|
463411
|
+
const relPath = relative16(cwd2, op.path);
|
|
463642
463412
|
const displayPath = relPath.startsWith("..") ? op.path : relPath;
|
|
463643
463413
|
const diffKey = fileEdit.toolCallId ? `${fileEdit.toolCallId}:${op.path}` : undefined;
|
|
463644
463414
|
const opDiff = diffKey && allDiffs ? allDiffs.get(diffKey) : undefined;
|
|
@@ -467175,11 +466945,11 @@ var init_HelpDialog = __esm(async () => {
|
|
|
467175
466945
|
|
|
467176
466946
|
// src/hooks/writer.ts
|
|
467177
466947
|
import { homedir as homedir50 } from "node:os";
|
|
467178
|
-
import { resolve as
|
|
466948
|
+
import { resolve as resolve40 } from "node:path";
|
|
467179
466949
|
function isProjectSettingsPathCollidingWithGlobal2(workingDirectory) {
|
|
467180
466950
|
const home = process.env.HOME || homedir50();
|
|
467181
|
-
const globalSettingsPath =
|
|
467182
|
-
const projectSettingsPath =
|
|
466951
|
+
const globalSettingsPath = resolve40(home, ".letta", "settings.json");
|
|
466952
|
+
const projectSettingsPath = resolve40(workingDirectory, ".letta", "settings.json");
|
|
467183
466953
|
return globalSettingsPath === projectSettingsPath;
|
|
467184
466954
|
}
|
|
467185
466955
|
function loadHooksFromLocation(location, workingDirectory = process.cwd()) {
|
|
@@ -472969,15 +472739,15 @@ var init_InputRich = __esm(async () => {
|
|
|
472969
472739
|
// src/cli/commands/install-github-app.ts
|
|
472970
472740
|
import { execFileSync as execFileSync7 } from "node:child_process";
|
|
472971
472741
|
import {
|
|
472972
|
-
existsSync as
|
|
472742
|
+
existsSync as existsSync68,
|
|
472973
472743
|
mkdirSync as mkdirSync46,
|
|
472974
472744
|
mkdtempSync as mkdtempSync6,
|
|
472975
|
-
readFileSync as
|
|
472745
|
+
readFileSync as readFileSync43,
|
|
472976
472746
|
rmSync as rmSync18,
|
|
472977
472747
|
writeFileSync as writeFileSync36
|
|
472978
472748
|
} from "node:fs";
|
|
472979
472749
|
import { tmpdir as tmpdir12 } from "node:os";
|
|
472980
|
-
import { dirname as
|
|
472750
|
+
import { dirname as dirname36, join as join88 } from "node:path";
|
|
472981
472751
|
function runCommand(command, args, cwd2, input) {
|
|
472982
472752
|
try {
|
|
472983
472753
|
return execFileSync7(command, args, {
|
|
@@ -473198,8 +472968,8 @@ async function createLettaAgent(apiKey, name) {
|
|
|
473198
472968
|
return createMinimalAgent(apiKey, name);
|
|
473199
472969
|
}
|
|
473200
472970
|
function cloneRepoToTemp(repo) {
|
|
473201
|
-
const tempDir = mkdtempSync6(
|
|
473202
|
-
const repoDir =
|
|
472971
|
+
const tempDir = mkdtempSync6(join88(tmpdir12(), "letta-install-github-app-"));
|
|
472972
|
+
const repoDir = join88(tempDir, "repo");
|
|
473203
472973
|
runCommand("gh", ["repo", "clone", repo, repoDir, "--", "--depth=1"]);
|
|
473204
472974
|
return { tempDir, repoDir };
|
|
473205
472975
|
}
|
|
@@ -473210,14 +472980,14 @@ function runGit7(args, cwd2) {
|
|
|
473210
472980
|
return runCommand("git", args, cwd2);
|
|
473211
472981
|
}
|
|
473212
472982
|
function writeWorkflow(repoDir, workflowPath, content) {
|
|
473213
|
-
const absolutePath =
|
|
473214
|
-
if (!
|
|
473215
|
-
mkdirSync46(
|
|
472983
|
+
const absolutePath = join88(repoDir, workflowPath);
|
|
472984
|
+
if (!existsSync68(dirname36(absolutePath))) {
|
|
472985
|
+
mkdirSync46(dirname36(absolutePath), { recursive: true });
|
|
473216
472986
|
}
|
|
473217
472987
|
const next = `${content.trimEnd()}
|
|
473218
472988
|
`;
|
|
473219
|
-
if (
|
|
473220
|
-
const previous =
|
|
472989
|
+
if (existsSync68(absolutePath)) {
|
|
472990
|
+
const previous = readFileSync43(absolutePath, "utf8");
|
|
473221
472991
|
if (previous === next) {
|
|
473222
472992
|
return false;
|
|
473223
472993
|
}
|
|
@@ -477106,9 +476876,9 @@ __export(exports_generate_memory_viewer, {
|
|
|
477106
476876
|
generateAndOpenMemoryViewer: () => generateAndOpenMemoryViewer
|
|
477107
476877
|
});
|
|
477108
476878
|
import { execFile as execFileCb7 } from "node:child_process";
|
|
477109
|
-
import { chmodSync as chmodSync7, existsSync as
|
|
476879
|
+
import { chmodSync as chmodSync7, existsSync as existsSync69, mkdirSync as mkdirSync47, writeFileSync as writeFileSync37 } from "node:fs";
|
|
477110
476880
|
import { homedir as homedir51 } from "node:os";
|
|
477111
|
-
import { join as
|
|
476881
|
+
import { join as join89 } from "node:path";
|
|
477112
476882
|
import { promisify as promisify18 } from "node:util";
|
|
477113
476883
|
function messagesFromOverview(overview) {
|
|
477114
476884
|
return overview.messages?.map((message) => ({
|
|
@@ -477146,7 +476916,7 @@ async function runGitSafe(cwd2, args) {
|
|
|
477146
476916
|
return "";
|
|
477147
476917
|
}
|
|
477148
476918
|
}
|
|
477149
|
-
function
|
|
476919
|
+
function parseFrontmatter2(raw2) {
|
|
477150
476920
|
if (!raw2.startsWith("---")) {
|
|
477151
476921
|
return { frontmatter: {}, body: raw2 };
|
|
477152
476922
|
}
|
|
@@ -477175,7 +476945,7 @@ function collectFiles2(memoryRoot) {
|
|
|
477175
476945
|
const fileNodes = getFileNodes(treeNodes);
|
|
477176
476946
|
return fileNodes.filter((n) => n.name.endsWith(".md")).map((n) => {
|
|
477177
476947
|
const raw2 = readFileContent(n.fullPath);
|
|
477178
|
-
const { frontmatter, body: body3 } =
|
|
476948
|
+
const { frontmatter, body: body3 } = parseFrontmatter2(raw2);
|
|
477179
476949
|
return {
|
|
477180
476950
|
path: n.relativePath,
|
|
477181
476951
|
isSystem: n.relativePath.startsWith("system/") || n.relativePath.startsWith("system\\"),
|
|
@@ -477417,7 +477187,7 @@ ${m4.body}` : m4.subject;
|
|
|
477417
477187
|
async function generateAndOpenMemoryViewer(agentId, options) {
|
|
477418
477188
|
const memoryRoot = getScopedMemoryFilesystemRoot(agentId);
|
|
477419
477189
|
const repoDir = memoryRoot;
|
|
477420
|
-
if (!
|
|
477190
|
+
if (!existsSync69(join89(repoDir, ".git"))) {
|
|
477421
477191
|
throw new Error("Memory viewer requires memfs. Run /memfs enable first.");
|
|
477422
477192
|
}
|
|
477423
477193
|
const data = await collectMemoryData(agentId, repoDir, memoryRoot, options?.conversationId);
|
|
@@ -477427,13 +477197,13 @@ async function generateAndOpenMemoryViewer(agentId, options) {
|
|
|
477427
477197
|
data.context = applyContextUsageSnapshot(data.context, options?.contextUsage);
|
|
477428
477198
|
const jsonPayload = JSON.stringify(data).replace(/</g, "\\u003c");
|
|
477429
477199
|
const html5 = memory_viewer_template_default.replace("<!--LETTA_DATA_PLACEHOLDER-->", () => jsonPayload);
|
|
477430
|
-
if (!
|
|
477200
|
+
if (!existsSync69(VIEWERS_DIR)) {
|
|
477431
477201
|
mkdirSync47(VIEWERS_DIR, { recursive: true, mode: 448 });
|
|
477432
477202
|
}
|
|
477433
477203
|
try {
|
|
477434
477204
|
chmodSync7(VIEWERS_DIR, 448);
|
|
477435
477205
|
} catch {}
|
|
477436
|
-
const filePath =
|
|
477206
|
+
const filePath = join89(VIEWERS_DIR, `memory-${encodeURIComponent(agentId)}.html`);
|
|
477437
477207
|
writeFileSync37(filePath, html5);
|
|
477438
477208
|
chmodSync7(filePath, 384);
|
|
477439
477209
|
const skipOpen = Boolean(process.env.TMUX) || Boolean(process.env.SSH_CONNECTION) || Boolean(process.env.SSH_TTY);
|
|
@@ -477459,13 +477229,13 @@ var init_generate_memory_viewer = __esm(() => {
|
|
|
477459
477229
|
init_local_memory_context();
|
|
477460
477230
|
init_memory_viewer_template();
|
|
477461
477231
|
execFile20 = promisify18(execFileCb7);
|
|
477462
|
-
VIEWERS_DIR =
|
|
477232
|
+
VIEWERS_DIR = join89(homedir51(), ".letta", "viewers");
|
|
477463
477233
|
REFLECTION_PATTERN = /\(reflection\)|🔮|reflection:/i;
|
|
477464
477234
|
});
|
|
477465
477235
|
|
|
477466
477236
|
// src/cli/components/MemfsTreeViewer.tsx
|
|
477467
|
-
import { existsSync as
|
|
477468
|
-
import { join as
|
|
477237
|
+
import { existsSync as existsSync70 } from "node:fs";
|
|
477238
|
+
import { join as join90 } from "node:path";
|
|
477469
477239
|
function renderTreePrefix(node) {
|
|
477470
477240
|
let prefix = "";
|
|
477471
477241
|
for (let i4 = 0;i4 < node.depth; i4++) {
|
|
@@ -477493,8 +477263,8 @@ function MemfsTreeViewer({
|
|
|
477493
477263
|
const [status, setStatus] = import_react88.useState(null);
|
|
477494
477264
|
const statusTimerRef = import_react88.useRef(null);
|
|
477495
477265
|
const memoryRoot = getScopedMemoryFilesystemRoot(agentId);
|
|
477496
|
-
const memoryExists =
|
|
477497
|
-
const hasGitRepo = import_react88.useMemo(() =>
|
|
477266
|
+
const memoryExists = existsSync70(memoryRoot);
|
|
477267
|
+
const hasGitRepo = import_react88.useMemo(() => existsSync70(join90(memoryRoot, ".git")), [memoryRoot]);
|
|
477498
477268
|
function showStatus(msg, durationMs) {
|
|
477499
477269
|
if (statusTimerRef.current)
|
|
477500
477270
|
clearTimeout(statusTimerRef.current);
|
|
@@ -479869,19 +479639,19 @@ var init_PersonalitySelector = __esm(async () => {
|
|
|
479869
479639
|
});
|
|
479870
479640
|
|
|
479871
479641
|
// src/utils/aws-credentials.ts
|
|
479872
|
-
import { readFile as
|
|
479642
|
+
import { readFile as readFile31 } from "node:fs/promises";
|
|
479873
479643
|
import { homedir as homedir52 } from "node:os";
|
|
479874
|
-
import { join as
|
|
479644
|
+
import { join as join91 } from "node:path";
|
|
479875
479645
|
async function parseAwsCredentials() {
|
|
479876
|
-
const credentialsPath =
|
|
479877
|
-
const configPath =
|
|
479646
|
+
const credentialsPath = join91(homedir52(), ".aws", "credentials");
|
|
479647
|
+
const configPath = join91(homedir52(), ".aws", "config");
|
|
479878
479648
|
const profiles = new Map;
|
|
479879
479649
|
try {
|
|
479880
|
-
const content = await
|
|
479650
|
+
const content = await readFile31(credentialsPath, "utf-8");
|
|
479881
479651
|
parseIniFile(content, profiles, false);
|
|
479882
479652
|
} catch {}
|
|
479883
479653
|
try {
|
|
479884
|
-
const content = await
|
|
479654
|
+
const content = await readFile31(configPath, "utf-8");
|
|
479885
479655
|
parseIniFile(content, profiles, true);
|
|
479886
479656
|
} catch {}
|
|
479887
479657
|
return Array.from(profiles.values());
|
|
@@ -481453,8 +481223,8 @@ function SkillsDialog({ onClose, agentId }) {
|
|
|
481453
481223
|
try {
|
|
481454
481224
|
const { discoverSkills: discoverSkills2, SKILLS_DIR: SKILLS_DIR2 } = await Promise.resolve().then(() => (init_skills5(), exports_skills2));
|
|
481455
481225
|
const { getSkillsDirectory: getSkillsDirectory2, getSkillSources: getSkillSources2 } = await Promise.resolve().then(() => (init_context(), exports_context));
|
|
481456
|
-
const { join:
|
|
481457
|
-
const skillsDir = getSkillsDirectory2() ||
|
|
481226
|
+
const { join: join92 } = await import("node:path");
|
|
481227
|
+
const skillsDir = getSkillsDirectory2() || join92(process.cwd(), SKILLS_DIR2);
|
|
481458
481228
|
const result2 = await discoverSkills2(skillsDir, agentId, {
|
|
481459
481229
|
sources: getSkillSources2()
|
|
481460
481230
|
});
|
|
@@ -484852,15 +484622,15 @@ function ToolsetSelector({
|
|
|
484852
484622
|
const solidLine = SOLID_LINE19.repeat(Math.max(terminalWidth, 10));
|
|
484853
484623
|
const [showAll, setShowAll] = import_react103.useState(false);
|
|
484854
484624
|
const [selectedIndex, setSelectedIndex] = import_react103.useState(0);
|
|
484855
|
-
const featuredToolsets = import_react103.useMemo(() =>
|
|
484625
|
+
const featuredToolsets = import_react103.useMemo(() => TOOLSET_OPTIONS.filter((toolset) => toolset.is_featured), []);
|
|
484856
484626
|
const visibleToolsets = import_react103.useMemo(() => {
|
|
484857
484627
|
if (showAll)
|
|
484858
|
-
return
|
|
484628
|
+
return TOOLSET_OPTIONS;
|
|
484859
484629
|
if (featuredToolsets.length > 0)
|
|
484860
484630
|
return featuredToolsets;
|
|
484861
|
-
return
|
|
484631
|
+
return TOOLSET_OPTIONS;
|
|
484862
484632
|
}, [featuredToolsets, showAll]);
|
|
484863
|
-
const canToggleShowAll = featuredToolsets.length <
|
|
484633
|
+
const canToggleShowAll = featuredToolsets.length < TOOLSET_OPTIONS.length;
|
|
484864
484634
|
import_react103.useEffect(() => {
|
|
484865
484635
|
if (selectedIndex >= visibleToolsets.length) {
|
|
484866
484636
|
setSelectedIndex(Math.max(0, visibleToolsets.length - 1));
|
|
@@ -484944,10 +484714,11 @@ function ToolsetSelector({
|
|
|
484944
484714
|
]
|
|
484945
484715
|
}, undefined, true, undefined, this);
|
|
484946
484716
|
}
|
|
484947
|
-
var import_react103, jsx_dev_runtime86, SOLID_LINE19 = "─"
|
|
484717
|
+
var import_react103, jsx_dev_runtime86, SOLID_LINE19 = "─";
|
|
484948
484718
|
var init_ToolsetSelector = __esm(async () => {
|
|
484949
484719
|
init_use_terminal_width();
|
|
484950
484720
|
init_toolset_labels();
|
|
484721
|
+
init_toolset_options();
|
|
484951
484722
|
init_colors();
|
|
484952
484723
|
await __promiseAll([
|
|
484953
484724
|
init_build4(),
|
|
@@ -484955,48 +484726,6 @@ var init_ToolsetSelector = __esm(async () => {
|
|
|
484955
484726
|
]);
|
|
484956
484727
|
import_react103 = __toESM(require_react(), 1);
|
|
484957
484728
|
jsx_dev_runtime86 = __toESM(require_jsx_dev_runtime(), 1);
|
|
484958
|
-
toolsets = [
|
|
484959
|
-
{
|
|
484960
|
-
id: "auto",
|
|
484961
|
-
label: "Auto",
|
|
484962
|
-
description: "Auto-select based on the model",
|
|
484963
|
-
isFeatured: true
|
|
484964
|
-
},
|
|
484965
|
-
{
|
|
484966
|
-
id: "none",
|
|
484967
|
-
label: "None",
|
|
484968
|
-
description: "Remove all Letta Code tools from your agent",
|
|
484969
|
-
isFeatured: true
|
|
484970
|
-
},
|
|
484971
|
-
{
|
|
484972
|
-
id: "default",
|
|
484973
|
-
label: "Claude toolset",
|
|
484974
|
-
description: "Optimized for Anthropic models",
|
|
484975
|
-
isFeatured: true
|
|
484976
|
-
},
|
|
484977
|
-
{
|
|
484978
|
-
id: "codex",
|
|
484979
|
-
label: "Codex toolset",
|
|
484980
|
-
description: "Optimized for GPT/Codex models",
|
|
484981
|
-
isFeatured: true
|
|
484982
|
-
},
|
|
484983
|
-
{
|
|
484984
|
-
id: "gemini",
|
|
484985
|
-
label: "Gemini toolset",
|
|
484986
|
-
description: "Optimized for Google Gemini models",
|
|
484987
|
-
isFeatured: true
|
|
484988
|
-
},
|
|
484989
|
-
{
|
|
484990
|
-
id: "codex_snake",
|
|
484991
|
-
label: "Codex toolset (snake_case)",
|
|
484992
|
-
description: "Optimized for GPT/Codex models (snake_case)"
|
|
484993
|
-
},
|
|
484994
|
-
{
|
|
484995
|
-
id: "gemini_snake",
|
|
484996
|
-
label: "Gemini toolset (snake_case)",
|
|
484997
|
-
description: "Optimized for Google Gemini models (snake_case)"
|
|
484998
|
-
}
|
|
484999
|
-
];
|
|
485000
484729
|
});
|
|
485001
484730
|
|
|
485002
484731
|
// src/cli/components/UserMessageRich.tsx
|
|
@@ -485616,9 +485345,9 @@ function getFileEditHeader(toolName2, toolArgs) {
|
|
|
485616
485345
|
} else if (operations.length === 1) {
|
|
485617
485346
|
const op = operations[0];
|
|
485618
485347
|
if (op) {
|
|
485619
|
-
const { relative:
|
|
485348
|
+
const { relative: relative17 } = __require("node:path");
|
|
485620
485349
|
const cwd3 = process.cwd();
|
|
485621
|
-
const relPath2 =
|
|
485350
|
+
const relPath2 = relative17(cwd3, op.path);
|
|
485622
485351
|
const displayPath3 = relPath2.startsWith("..") ? op.path : relPath2;
|
|
485623
485352
|
if (op.kind === "add")
|
|
485624
485353
|
return `Write to ${displayPath3}?`;
|
|
@@ -485632,14 +485361,14 @@ function getFileEditHeader(toolName2, toolArgs) {
|
|
|
485632
485361
|
return "Apply patch?";
|
|
485633
485362
|
}
|
|
485634
485363
|
const filePath = args.file_path || "";
|
|
485635
|
-
const { relative:
|
|
485364
|
+
const { relative: relative16 } = __require("node:path");
|
|
485636
485365
|
const cwd2 = process.cwd();
|
|
485637
|
-
const relPath =
|
|
485366
|
+
const relPath = relative16(cwd2, filePath);
|
|
485638
485367
|
const displayPath2 = relPath.startsWith("..") ? filePath : relPath;
|
|
485639
485368
|
if (t2 === "write" || t2 === "write_file" || t2 === "writefile" || t2 === "write_file_gemini" || t2 === "writefilegemini") {
|
|
485640
|
-
const { existsSync:
|
|
485369
|
+
const { existsSync: existsSync71 } = __require("node:fs");
|
|
485641
485370
|
try {
|
|
485642
|
-
if (
|
|
485371
|
+
if (existsSync71(filePath)) {
|
|
485643
485372
|
return `Overwrite ${displayPath2}?`;
|
|
485644
485373
|
}
|
|
485645
485374
|
} catch {}
|
|
@@ -485722,9 +485451,9 @@ var init_ApprovalPreview = __esm(async () => {
|
|
|
485722
485451
|
/* @__PURE__ */ jsx_dev_runtime92.jsxDEV(Box_default, {
|
|
485723
485452
|
flexDirection: "column",
|
|
485724
485453
|
children: operations.map((op, idx) => {
|
|
485725
|
-
const { relative:
|
|
485454
|
+
const { relative: relative16 } = __require("node:path");
|
|
485726
485455
|
const cwd2 = process.cwd();
|
|
485727
|
-
const relPath =
|
|
485456
|
+
const relPath = relative16(cwd2, op.path);
|
|
485728
485457
|
const displayPath2 = relPath.startsWith("..") ? op.path : relPath;
|
|
485729
485458
|
const diffKey = toolCallId ? `${toolCallId}:${op.path}` : undefined;
|
|
485730
485459
|
const opDiff = diffKey && allDiffs ? allDiffs.get(diffKey) : undefined;
|
|
@@ -500875,9 +500604,9 @@ __export(exports_generate_diff_viewer, {
|
|
|
500875
500604
|
generateAndOpenDiffViewer: () => generateAndOpenDiffViewer
|
|
500876
500605
|
});
|
|
500877
500606
|
import { execFile as execFileCb8 } from "node:child_process";
|
|
500878
|
-
import { chmodSync as chmodSync8, existsSync as
|
|
500607
|
+
import { chmodSync as chmodSync8, existsSync as existsSync71, mkdirSync as mkdirSync48, writeFileSync as writeFileSync38 } from "node:fs";
|
|
500879
500608
|
import { homedir as homedir53 } from "node:os";
|
|
500880
|
-
import { isAbsolute as
|
|
500609
|
+
import { isAbsolute as isAbsolute31, join as join92, resolve as resolve41 } from "node:path";
|
|
500881
500610
|
import { promisify as promisify19 } from "node:util";
|
|
500882
500611
|
async function runGit8(cwd2, args) {
|
|
500883
500612
|
try {
|
|
@@ -501075,7 +500804,7 @@ function escapeHtml3(value) {
|
|
|
501075
500804
|
function resolveTargetPath(targetPath) {
|
|
501076
500805
|
if (!targetPath?.trim())
|
|
501077
500806
|
return process.cwd();
|
|
501078
|
-
return
|
|
500807
|
+
return isAbsolute31(targetPath) ? targetPath : resolve41(process.cwd(), targetPath);
|
|
501079
500808
|
}
|
|
501080
500809
|
function shouldSkipOpen() {
|
|
501081
500810
|
return Boolean(process.env.TMUX) || Boolean(process.env.SSH_CONNECTION) || Boolean(process.env.SSH_TTY);
|
|
@@ -501096,13 +500825,13 @@ async function generateAndOpenDiffViewer(targetPath) {
|
|
|
501096
500825
|
};
|
|
501097
500826
|
const jsonPayload = JSON.stringify(payload).replace(/</g, "\\u003c");
|
|
501098
500827
|
const html5 = diff_viewer_template_default.replace("<!--LETTA_DIFF_DATA_PLACEHOLDER-->", () => jsonPayload);
|
|
501099
|
-
if (!
|
|
500828
|
+
if (!existsSync71(VIEWERS_DIR2)) {
|
|
501100
500829
|
mkdirSync48(VIEWERS_DIR2, { recursive: true, mode: 448 });
|
|
501101
500830
|
}
|
|
501102
500831
|
try {
|
|
501103
500832
|
chmodSync8(VIEWERS_DIR2, 448);
|
|
501104
500833
|
} catch {}
|
|
501105
|
-
const filePath =
|
|
500834
|
+
const filePath = join92(VIEWERS_DIR2, `diff-${encodeURIComponent(worktreePath)}.html`);
|
|
501106
500835
|
writeFileSync38(filePath, html5);
|
|
501107
500836
|
chmodSync8(filePath, 384);
|
|
501108
500837
|
const skipOpen = shouldSkipOpen();
|
|
@@ -501173,7 +500902,7 @@ var init_generate_diff_viewer = __esm(() => {
|
|
|
501173
500902
|
init_ssr();
|
|
501174
500903
|
init_diff_viewer_template();
|
|
501175
500904
|
execFile21 = promisify19(execFileCb8);
|
|
501176
|
-
VIEWERS_DIR2 =
|
|
500905
|
+
VIEWERS_DIR2 = join92(homedir53(), ".letta", "viewers");
|
|
501177
500906
|
GIT_MAX_BUFFER = 50 * 1024 * 1024;
|
|
501178
500907
|
});
|
|
501179
500908
|
|
|
@@ -503136,16 +502865,16 @@ __export(exports_shell_aliases, {
|
|
|
503136
502865
|
expandAliases: () => expandAliases,
|
|
503137
502866
|
clearAliasCache: () => clearAliasCache
|
|
503138
502867
|
});
|
|
503139
|
-
import { existsSync as
|
|
502868
|
+
import { existsSync as existsSync72, readFileSync as readFileSync44 } from "node:fs";
|
|
503140
502869
|
import { homedir as homedir54 } from "node:os";
|
|
503141
|
-
import { join as
|
|
502870
|
+
import { join as join93 } from "node:path";
|
|
503142
502871
|
function parseAliasesFromFile(filePath) {
|
|
503143
502872
|
const aliases = new Map;
|
|
503144
|
-
if (!
|
|
502873
|
+
if (!existsSync72(filePath)) {
|
|
503145
502874
|
return aliases;
|
|
503146
502875
|
}
|
|
503147
502876
|
try {
|
|
503148
|
-
const content =
|
|
502877
|
+
const content = readFileSync44(filePath, "utf-8");
|
|
503149
502878
|
const lines = content.split(`
|
|
503150
502879
|
`);
|
|
503151
502880
|
let inFunction = false;
|
|
@@ -503210,7 +502939,7 @@ function loadAliases(forceReload = false) {
|
|
|
503210
502939
|
const home = homedir54();
|
|
503211
502940
|
const allAliases = new Map;
|
|
503212
502941
|
for (const file of ALIAS_FILES) {
|
|
503213
|
-
const filePath =
|
|
502942
|
+
const filePath = join93(home, file);
|
|
503214
502943
|
const fileAliases = parseAliasesFromFile(filePath);
|
|
503215
502944
|
for (const [name, value] of fileAliases) {
|
|
503216
502945
|
allAliases.set(name, value);
|
|
@@ -504363,7 +504092,7 @@ var init_system_reminders = __esm(() => {
|
|
|
504363
504092
|
// src/cli/app/use-conversation-loop.ts
|
|
504364
504093
|
import { randomUUID as randomUUID41 } from "node:crypto";
|
|
504365
504094
|
function sleep11(ms) {
|
|
504366
|
-
return new Promise((
|
|
504095
|
+
return new Promise((resolve42) => setTimeout(resolve42, ms));
|
|
504367
504096
|
}
|
|
504368
504097
|
function makeExecutionPhaseHook(setExecutionPhase) {
|
|
504369
504098
|
return ({ chunk: chunk2 }) => {
|
|
@@ -504819,7 +504548,7 @@ function useConversationLoop(ctx) {
|
|
|
504819
504548
|
cancelled = true;
|
|
504820
504549
|
break;
|
|
504821
504550
|
}
|
|
504822
|
-
await new Promise((
|
|
504551
|
+
await new Promise((resolve42) => setTimeout(resolve42, 100));
|
|
504823
504552
|
}
|
|
504824
504553
|
buffersRef.current.byId.delete(statusId);
|
|
504825
504554
|
buffersRef.current.order = buffersRef.current.order.filter((id2) => id2 !== statusId);
|
|
@@ -504863,7 +504592,7 @@ function useConversationLoop(ctx) {
|
|
|
504863
504592
|
cancelled = true;
|
|
504864
504593
|
break;
|
|
504865
504594
|
}
|
|
504866
|
-
await new Promise((
|
|
504595
|
+
await new Promise((resolve42) => setTimeout(resolve42, 100));
|
|
504867
504596
|
}
|
|
504868
504597
|
if (retryStatusId) {
|
|
504869
504598
|
buffersRef.current.byId.delete(retryStatusId);
|
|
@@ -505681,7 +505410,7 @@ ${feedback}
|
|
|
505681
505410
|
});
|
|
505682
505411
|
buffersRef.current.order.push(statusId);
|
|
505683
505412
|
refreshDerived();
|
|
505684
|
-
await new Promise((
|
|
505413
|
+
await new Promise((resolve42) => setTimeout(resolve42, delayMs));
|
|
505685
505414
|
buffersRef.current.byId.delete(statusId);
|
|
505686
505415
|
buffersRef.current.order = buffersRef.current.order.filter((id2) => id2 !== statusId);
|
|
505687
505416
|
refreshDerived();
|
|
@@ -505721,7 +505450,7 @@ ${feedback}
|
|
|
505721
505450
|
cancelled = true;
|
|
505722
505451
|
break;
|
|
505723
505452
|
}
|
|
505724
|
-
await new Promise((
|
|
505453
|
+
await new Promise((resolve42) => setTimeout(resolve42, 100));
|
|
505725
505454
|
}
|
|
505726
505455
|
if (retryStatusId) {
|
|
505727
505456
|
buffersRef.current.byId.delete(retryStatusId);
|
|
@@ -507467,7 +507196,7 @@ The deployment target for this project is CITATION-DOGFOOD-OK.
|
|
|
507467
507196
|
|
|
507468
507197
|
// src/mods/learning-harness.ts
|
|
507469
507198
|
import { spawn as spawn14 } from "node:child_process";
|
|
507470
|
-
import { access as
|
|
507199
|
+
import { access as access3, copyFile as copyFile2, mkdir as mkdir19, readFile as readFile32, writeFile as writeFile21 } from "node:fs/promises";
|
|
507471
507200
|
import path51 from "node:path";
|
|
507472
507201
|
function slugify2(value) {
|
|
507473
507202
|
const slug = value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
@@ -507491,9 +507220,9 @@ function hasText(value) {
|
|
|
507491
507220
|
return typeof value === "string" && value.trim().length > 0;
|
|
507492
507221
|
}
|
|
507493
507222
|
function markerChecks(markers, haystack) {
|
|
507494
|
-
return (markers ?? []).map((
|
|
507495
|
-
marker,
|
|
507496
|
-
present: haystack.includes(
|
|
507223
|
+
return (markers ?? []).map((marker2) => ({
|
|
507224
|
+
marker: marker2,
|
|
507225
|
+
present: haystack.includes(marker2)
|
|
507497
507226
|
}));
|
|
507498
507227
|
}
|
|
507499
507228
|
function asStringArray(value) {
|
|
@@ -507705,7 +507434,7 @@ function safeJoin(root2, relativePath) {
|
|
|
507705
507434
|
}
|
|
507706
507435
|
async function fileExists(filePath) {
|
|
507707
507436
|
try {
|
|
507708
|
-
await
|
|
507437
|
+
await access3(filePath);
|
|
507709
507438
|
return true;
|
|
507710
507439
|
} catch {
|
|
507711
507440
|
return false;
|
|
@@ -507715,22 +507444,22 @@ async function existingPath(filePath) {
|
|
|
507715
507444
|
return await fileExists(filePath) ? filePath : undefined;
|
|
507716
507445
|
}
|
|
507717
507446
|
async function writeJsonArtifact(filePath, value) {
|
|
507718
|
-
await
|
|
507447
|
+
await writeFile21(filePath, `${JSON.stringify(value, null, 2)}
|
|
507719
507448
|
`, "utf8");
|
|
507720
507449
|
}
|
|
507721
507450
|
async function writeCommandArtifacts(prefix, command, args, result2) {
|
|
507722
|
-
await
|
|
507451
|
+
await writeFile21(`${prefix}.command.txt`, `${renderCommand(command, args)}
|
|
507723
507452
|
`, "utf8");
|
|
507724
|
-
await
|
|
507725
|
-
await
|
|
507453
|
+
await writeFile21(`${prefix}.stdout`, result2.stdout, "utf8");
|
|
507454
|
+
await writeFile21(`${prefix}.stderr`, result2.stderr, "utf8");
|
|
507726
507455
|
await writeJsonArtifact(`${prefix}.result.json`, result2);
|
|
507727
507456
|
}
|
|
507728
507457
|
async function prepareMemoryFiles(memoryDir, memoryFiles) {
|
|
507729
|
-
await
|
|
507458
|
+
await mkdir19(memoryDir, { recursive: true });
|
|
507730
507459
|
for (const [relativePath, content] of Object.entries(memoryFiles ?? {})) {
|
|
507731
507460
|
const filePath = safeJoin(memoryDir, relativePath);
|
|
507732
|
-
await
|
|
507733
|
-
await
|
|
507461
|
+
await mkdir19(path51.dirname(filePath), { recursive: true });
|
|
507462
|
+
await writeFile21(filePath, content, "utf8");
|
|
507734
507463
|
}
|
|
507735
507464
|
}
|
|
507736
507465
|
function renderEvaluationPrompt(prompt, memoryDir) {
|
|
@@ -508393,7 +508122,7 @@ function renderProposerGuide(params) {
|
|
|
508393
508122
|
`;
|
|
508394
508123
|
}
|
|
508395
508124
|
async function writeHistoryArtifacts(params) {
|
|
508396
|
-
await
|
|
508125
|
+
await writeFile21(params.historyPath, renderHistoryIndex({
|
|
508397
508126
|
attempts: params.attempts,
|
|
508398
508127
|
historyManifestPath: params.historyManifestPath,
|
|
508399
508128
|
proposerGuidePath: params.proposerGuidePath,
|
|
@@ -508401,11 +508130,11 @@ async function writeHistoryArtifacts(params) {
|
|
|
508401
508130
|
spec: params.spec
|
|
508402
508131
|
}), "utf8");
|
|
508403
508132
|
await writeJsonArtifact(params.historyManifestPath, buildHistoryManifest(params));
|
|
508404
|
-
await
|
|
508133
|
+
await writeFile21(params.proposerGuidePath, renderProposerGuide(params), "utf8");
|
|
508405
508134
|
}
|
|
508406
508135
|
async function defaultCommandRunner(command, args, options) {
|
|
508407
508136
|
const startedAt = Date.now();
|
|
508408
|
-
return new Promise((
|
|
508137
|
+
return new Promise((resolve42) => {
|
|
508409
508138
|
const child = spawn14(command, args, {
|
|
508410
508139
|
cwd: options.cwd,
|
|
508411
508140
|
env: options.env,
|
|
@@ -508432,7 +508161,7 @@ async function defaultCommandRunner(command, args, options) {
|
|
|
508432
508161
|
});
|
|
508433
508162
|
child.on("close", (exitCode) => {
|
|
508434
508163
|
clearTimeout(timeout);
|
|
508435
|
-
|
|
508164
|
+
resolve42({
|
|
508436
508165
|
args,
|
|
508437
508166
|
command,
|
|
508438
508167
|
cwd: options.cwd,
|
|
@@ -508492,7 +508221,7 @@ function createScenarioSuiteEvaluator(params) {
|
|
|
508492
508221
|
outputFormat
|
|
508493
508222
|
})
|
|
508494
508223
|
];
|
|
508495
|
-
await
|
|
508224
|
+
await writeFile21(hasConfiguredScenarios ? path51.join(scenarioDir, "prompt.md") : path51.join(context3.runDir, "eval-prompt.md"), evalPrompt, "utf8");
|
|
508496
508225
|
const scenarioEvalResult = await context3.runner(context3.cliCommand, evalArgs, {
|
|
508497
508226
|
cwd: context3.repoRoot,
|
|
508498
508227
|
env: {
|
|
@@ -508654,7 +508383,7 @@ async function runModLearningCandidate(params) {
|
|
|
508654
508383
|
});
|
|
508655
508384
|
};
|
|
508656
508385
|
emitProgress("preparing", params.candidateCount > 1 ? `Preparing optimization iteration ${params.candidateIndex}/${params.candidateCount}` : "Preparing mod learning run");
|
|
508657
|
-
await
|
|
508386
|
+
await mkdir19(candidateDir, { recursive: true });
|
|
508658
508387
|
await writeJsonArtifact(path51.join(runDir, "env.snapshot.json"), options.spec);
|
|
508659
508388
|
let generationResult = null;
|
|
508660
508389
|
if (options.candidateSourcePath) {
|
|
@@ -508684,7 +508413,7 @@ async function runModLearningCandidate(params) {
|
|
|
508684
508413
|
outputFormat: "json"
|
|
508685
508414
|
})
|
|
508686
508415
|
];
|
|
508687
|
-
await
|
|
508416
|
+
await writeFile21(path51.join(runDir, "generation-prompt.md"), generationPrompt, "utf8");
|
|
508688
508417
|
generationResult = await params.runner(params.cliCommand, generationArgs, {
|
|
508689
508418
|
cwd: repoRoot,
|
|
508690
508419
|
env: {
|
|
@@ -508741,7 +508470,7 @@ async function runModLearningCandidate(params) {
|
|
|
508741
508470
|
if (passed && options.promoteToPath) {
|
|
508742
508471
|
emitProgress("promoting", "Promoting passing candidate mod");
|
|
508743
508472
|
promotedToPath = path51.resolve(repoRoot, options.promoteToPath);
|
|
508744
|
-
await
|
|
508473
|
+
await mkdir19(path51.dirname(promotedToPath), { recursive: true });
|
|
508745
508474
|
await copyFile2(candidatePath, promotedToPath);
|
|
508746
508475
|
}
|
|
508747
508476
|
const reportPath = path51.join(runDir, "report.md");
|
|
@@ -508763,7 +508492,7 @@ async function runModLearningCandidate(params) {
|
|
|
508763
508492
|
spec: options.spec
|
|
508764
508493
|
};
|
|
508765
508494
|
await writeJsonArtifact(path51.join(runDir, "report.json"), report);
|
|
508766
|
-
await
|
|
508495
|
+
await writeFile21(reportPath, renderMarkdownReport(report), "utf8");
|
|
508767
508496
|
await writeCandidateManifest(report);
|
|
508768
508497
|
emitProgress("done", params.candidateCount > 1 ? `Optimization iteration ${params.candidateIndex}/${params.candidateCount} complete` : "mod optimization complete", {
|
|
508769
508498
|
attempts: [...params.previousAttempts, summarizeAttempt(report)],
|
|
@@ -508792,7 +508521,7 @@ async function runModLearning(options) {
|
|
|
508792
508521
|
const cliCommand = normalizedOptions.cliCommand ?? "bun";
|
|
508793
508522
|
const cliArgsPrefix = normalizedOptions.cliArgsPrefix ?? ["run", "dev"];
|
|
508794
508523
|
const baseEnv = normalizedOptions.env ?? process.env;
|
|
508795
|
-
await
|
|
508524
|
+
await mkdir19(runDir, { recursive: true });
|
|
508796
508525
|
await writeJsonArtifact(path51.join(runDir, "env.snapshot.json"), normalizedOptions.spec);
|
|
508797
508526
|
if (candidateCount === 1) {
|
|
508798
508527
|
const report2 = await runModLearningCandidate({
|
|
@@ -508903,7 +508632,7 @@ async function runModLearning(options) {
|
|
|
508903
508632
|
selectedCandidateIndex
|
|
508904
508633
|
});
|
|
508905
508634
|
promotedToPath = path51.resolve(repoRoot, normalizedOptions.promoteToPath);
|
|
508906
|
-
await
|
|
508635
|
+
await mkdir19(path51.dirname(promotedToPath), { recursive: true });
|
|
508907
508636
|
await copyFile2(selectedReport.candidatePath, promotedToPath);
|
|
508908
508637
|
}
|
|
508909
508638
|
const reportPath = path51.join(runDir, "report.md");
|
|
@@ -508941,7 +508670,7 @@ async function runModLearning(options) {
|
|
|
508941
508670
|
spec: normalizedOptions.spec
|
|
508942
508671
|
});
|
|
508943
508672
|
await writeJsonArtifact(path51.join(runDir, "report.json"), report);
|
|
508944
|
-
await
|
|
508673
|
+
await writeFile21(reportPath, renderMarkdownReport(report), "utf8");
|
|
508945
508674
|
normalizedOptions.onProgress?.({
|
|
508946
508675
|
candidateCount,
|
|
508947
508676
|
candidateIndex: selectedCandidateIndex,
|
|
@@ -508959,7 +508688,7 @@ async function runModLearning(options) {
|
|
|
508959
508688
|
return report;
|
|
508960
508689
|
}
|
|
508961
508690
|
async function readModLearningEnv(envPath) {
|
|
508962
|
-
return JSON.parse(await
|
|
508691
|
+
return JSON.parse(await readFile32(envPath, "utf8"));
|
|
508963
508692
|
}
|
|
508964
508693
|
var init_learning_harness = __esm(async () => {
|
|
508965
508694
|
await init_mod_engine();
|
|
@@ -509669,8 +509398,6 @@ var init_command_routing = __esm(() => {
|
|
|
509669
509398
|
"/search",
|
|
509670
509399
|
"/memory",
|
|
509671
509400
|
"/feedback",
|
|
509672
|
-
"/export",
|
|
509673
|
-
"/download",
|
|
509674
509401
|
"/mods",
|
|
509675
509402
|
"/reasoning-tab",
|
|
509676
509403
|
"/secret",
|
|
@@ -511199,7 +510926,7 @@ __export(exports_worktree_diff_list, {
|
|
|
511199
510926
|
listWorktreeDiffOptions: () => listWorktreeDiffOptions
|
|
511200
510927
|
});
|
|
511201
510928
|
import { execFile as execFileCb9 } from "node:child_process";
|
|
511202
|
-
import { basename as
|
|
510929
|
+
import { basename as basename30 } from "node:path";
|
|
511203
510930
|
import { promisify as promisify20 } from "node:util";
|
|
511204
510931
|
async function runGit9(cwd2, args) {
|
|
511205
510932
|
try {
|
|
@@ -511248,7 +510975,7 @@ function parseWorktreeList(output, currentPath) {
|
|
|
511248
510975
|
if (current?.path) {
|
|
511249
510976
|
worktrees.push({
|
|
511250
510977
|
path: current.path,
|
|
511251
|
-
name:
|
|
510978
|
+
name: basename30(current.path),
|
|
511252
510979
|
branch: current.branch ?? "detached",
|
|
511253
510980
|
head: current.head ?? "",
|
|
511254
510981
|
isCurrent: current.path === currentPath,
|
|
@@ -511274,7 +511001,7 @@ function parseWorktreeList(output, currentPath) {
|
|
|
511274
511001
|
if (current?.path) {
|
|
511275
511002
|
worktrees.push({
|
|
511276
511003
|
path: current.path,
|
|
511277
|
-
name:
|
|
511004
|
+
name: basename30(current.path),
|
|
511278
511005
|
branch: current.branch ?? "detached",
|
|
511279
511006
|
head: current.head ?? "",
|
|
511280
511007
|
isCurrent: current.path === currentPath,
|
|
@@ -511338,107 +511065,6 @@ var init_worktree_diff_list = __esm(() => {
|
|
|
511338
511065
|
GIT_MAX_BUFFER2 = 10 * 1024 * 1024;
|
|
511339
511066
|
});
|
|
511340
511067
|
|
|
511341
|
-
// src/agent/export.ts
|
|
511342
|
-
var exports_export = {};
|
|
511343
|
-
__export(exports_export, {
|
|
511344
|
-
packageSkills: () => packageSkills
|
|
511345
|
-
});
|
|
511346
|
-
import { readdir as readdir17, readFile as readFile34 } from "node:fs/promises";
|
|
511347
|
-
import { relative as relative17, resolve as resolve44 } from "node:path";
|
|
511348
|
-
async function packageSkills(agentId, skillsDir) {
|
|
511349
|
-
const skills = [];
|
|
511350
|
-
const skillNames = new Set;
|
|
511351
|
-
const dirsToCheck = skillsDir ? [skillsDir] : [
|
|
511352
|
-
agentId && getAgentSkillsDir(agentId),
|
|
511353
|
-
resolve44(process.cwd(), ".skills"),
|
|
511354
|
-
resolve44(process.env.HOME || "~", ".letta", "skills")
|
|
511355
|
-
].filter((dir) => Boolean(dir));
|
|
511356
|
-
for (const baseDir of dirsToCheck) {
|
|
511357
|
-
try {
|
|
511358
|
-
const entries = await readdir17(baseDir, { withFileTypes: true });
|
|
511359
|
-
for (const entry of entries) {
|
|
511360
|
-
if (!entry.isDirectory())
|
|
511361
|
-
continue;
|
|
511362
|
-
if (skillNames.has(entry.name))
|
|
511363
|
-
continue;
|
|
511364
|
-
const skillDir = resolve44(baseDir, entry.name);
|
|
511365
|
-
const skillMdPath = resolve44(skillDir, "SKILL.md");
|
|
511366
|
-
try {
|
|
511367
|
-
await readFile34(skillMdPath, "utf-8");
|
|
511368
|
-
} catch {
|
|
511369
|
-
console.warn(`Skipping invalid skill ${entry.name}: missing SKILL.md`);
|
|
511370
|
-
continue;
|
|
511371
|
-
}
|
|
511372
|
-
const sourceUrl = skillsDir ? null : await findSkillSourceUrl(entry.name);
|
|
511373
|
-
const skill2 = { name: entry.name };
|
|
511374
|
-
if (sourceUrl) {
|
|
511375
|
-
skill2.source_url = sourceUrl;
|
|
511376
|
-
} else {
|
|
511377
|
-
skill2.files = await readSkillFiles(skillDir);
|
|
511378
|
-
}
|
|
511379
|
-
skills.push(skill2);
|
|
511380
|
-
skillNames.add(entry.name);
|
|
511381
|
-
}
|
|
511382
|
-
} catch (error5) {
|
|
511383
|
-
if (error5.code !== "ENOENT") {
|
|
511384
|
-
throw error5;
|
|
511385
|
-
}
|
|
511386
|
-
}
|
|
511387
|
-
}
|
|
511388
|
-
return skills;
|
|
511389
|
-
}
|
|
511390
|
-
async function readSkillFiles(skillDir) {
|
|
511391
|
-
const files = {};
|
|
511392
|
-
async function walk3(dir) {
|
|
511393
|
-
const entries = await readdir17(dir, { withFileTypes: true });
|
|
511394
|
-
for (const entry of entries) {
|
|
511395
|
-
const fullPath = resolve44(dir, entry.name);
|
|
511396
|
-
if (entry.isDirectory()) {
|
|
511397
|
-
await walk3(fullPath);
|
|
511398
|
-
} else {
|
|
511399
|
-
const content = await readFile34(fullPath, "utf-8");
|
|
511400
|
-
const relativePath = relative17(skillDir, fullPath).replace(/\\/g, "/");
|
|
511401
|
-
files[relativePath] = content;
|
|
511402
|
-
}
|
|
511403
|
-
}
|
|
511404
|
-
}
|
|
511405
|
-
await walk3(skillDir);
|
|
511406
|
-
return files;
|
|
511407
|
-
}
|
|
511408
|
-
async function findSkillSourceUrl(skillName) {
|
|
511409
|
-
for (const repoPath of SKILL_REPOS) {
|
|
511410
|
-
if (!dirCache.has(repoPath)) {
|
|
511411
|
-
dirCache.set(repoPath, await fetchGitHubDirs(repoPath));
|
|
511412
|
-
}
|
|
511413
|
-
if (dirCache.get(repoPath)?.has(skillName)) {
|
|
511414
|
-
return `${repoPath}/${skillName}`;
|
|
511415
|
-
}
|
|
511416
|
-
}
|
|
511417
|
-
return null;
|
|
511418
|
-
}
|
|
511419
|
-
async function fetchGitHubDirs(path53) {
|
|
511420
|
-
const [owner, repo, branch, ...pathParts] = path53.split("/");
|
|
511421
|
-
if (!owner || !repo || !branch)
|
|
511422
|
-
return new Set;
|
|
511423
|
-
try {
|
|
511424
|
-
const { fetchGitHubContents: fetchGitHubContents2, parseDirNames: parseDirNames2 } = await Promise.resolve().then(() => exports_github_utils);
|
|
511425
|
-
const entries = await fetchGitHubContents2(owner, repo, branch, pathParts.join("/"));
|
|
511426
|
-
return parseDirNames2(entries);
|
|
511427
|
-
} catch {
|
|
511428
|
-
return new Set;
|
|
511429
|
-
}
|
|
511430
|
-
}
|
|
511431
|
-
var SKILL_REPOS, dirCache;
|
|
511432
|
-
var init_export2 = __esm(() => {
|
|
511433
|
-
init_skills5();
|
|
511434
|
-
SKILL_REPOS = [
|
|
511435
|
-
"letta-ai/skills/main/tools",
|
|
511436
|
-
"letta-ai/skills/main/letta",
|
|
511437
|
-
"anthropics/skills/main/skills"
|
|
511438
|
-
];
|
|
511439
|
-
dirCache = new Map;
|
|
511440
|
-
});
|
|
511441
|
-
|
|
511442
511068
|
// src/cli/helpers/conversation-switch-alert.ts
|
|
511443
511069
|
var exports_conversation_switch_alert = {};
|
|
511444
511070
|
__export(exports_conversation_switch_alert, {
|
|
@@ -511532,9 +511158,9 @@ var init_conversation_switch_alert = __esm(() => {
|
|
|
511532
511158
|
|
|
511533
511159
|
// src/cli/app/use-submit-handler.ts
|
|
511534
511160
|
import { randomUUID as randomUUID43 } from "node:crypto";
|
|
511535
|
-
import { existsSync as
|
|
511161
|
+
import { existsSync as existsSync73, readFileSync as readFileSync45, renameSync as renameSync8 } from "node:fs";
|
|
511536
511162
|
import { tmpdir as tmpdir13 } from "node:os";
|
|
511537
|
-
import { join as
|
|
511163
|
+
import { join as join94 } from "node:path";
|
|
511538
511164
|
async function findCustomCommandByName(commandName) {
|
|
511539
511165
|
const { findCustomCommand: findCustomCommand2 } = await Promise.resolve().then(() => (init_custom(), exports_custom));
|
|
511540
511166
|
return findCustomCommand2(commandName);
|
|
@@ -512234,12 +511860,12 @@ ${SYSTEM_REMINDER_CLOSE}`),
|
|
|
512234
511860
|
try {
|
|
512235
511861
|
const memoryRoot = getScopedMemoryFilesystemRoot(agentId);
|
|
512236
511862
|
const personaCandidates = [
|
|
512237
|
-
|
|
512238
|
-
|
|
511863
|
+
join94(memoryRoot, "system", "persona.md"),
|
|
511864
|
+
join94(memoryRoot, "memory", "system", "persona.md")
|
|
512239
511865
|
];
|
|
512240
|
-
const personaPath = personaCandidates.find((candidate) =>
|
|
511866
|
+
const personaPath = personaCandidates.find((candidate) => existsSync73(candidate));
|
|
512241
511867
|
if (personaPath) {
|
|
512242
|
-
const personaContent =
|
|
511868
|
+
const personaContent = readFileSync45(personaPath, "utf-8");
|
|
512243
511869
|
setCurrentPersonalityId(detectPersonalityFromPersonaFile(personaContent));
|
|
512244
511870
|
} else {
|
|
512245
511871
|
setCurrentPersonalityId(null);
|
|
@@ -512991,42 +512617,6 @@ Tip: Use /clear instead to clear the current message buffer.`;
|
|
|
512991
512617
|
cmd.finish(output, true);
|
|
512992
512618
|
return { submitted: true };
|
|
512993
512619
|
}
|
|
512994
|
-
if (msg.trim() === "/export" || msg.trim() === "/download") {
|
|
512995
|
-
const cmd = commandRunner.start(msg.trim(), "Exporting agent file...");
|
|
512996
|
-
if (!getBackend().capabilities.agentFileImportExport) {
|
|
512997
|
-
cmd.fail("AgentFile export is not supported by the local backend yet.");
|
|
512998
|
-
return { submitted: true };
|
|
512999
|
-
}
|
|
513000
|
-
setCommandRunning(true);
|
|
513001
|
-
try {
|
|
513002
|
-
const client = await getClient();
|
|
513003
|
-
const exportParams = {};
|
|
513004
|
-
if (conversationId !== "default" && conversationId !== agentId) {
|
|
513005
|
-
exportParams.conversation_id = conversationId;
|
|
513006
|
-
}
|
|
513007
|
-
const { packageSkills: packageSkills2 } = await Promise.resolve().then(() => (init_export2(), exports_export));
|
|
513008
|
-
const skills = await packageSkills2(agentId);
|
|
513009
|
-
const baseContent = await client.agents.exportFile(agentId, exportParams);
|
|
513010
|
-
const fileContent = typeof baseContent === "string" ? JSON.parse(baseContent) : baseContent;
|
|
513011
|
-
if (skills.length > 0) {
|
|
513012
|
-
fileContent.skills = skills;
|
|
513013
|
-
}
|
|
513014
|
-
const fileName = exportParams.conversation_id ? `${exportParams.conversation_id}.af` : `${agentId}.af`;
|
|
513015
|
-
writeFileSync39(fileName, JSON.stringify(fileContent, null, 2));
|
|
513016
|
-
let summary = `AgentFile exported to ${fileName}`;
|
|
513017
|
-
if (skills.length > 0) {
|
|
513018
|
-
summary += `
|
|
513019
|
-
\uD83D\uDCE6 Included ${skills.length} skill(s): ${skills.map((s3) => s3.name).join(", ")}`;
|
|
513020
|
-
}
|
|
513021
|
-
cmd.finish(summary, true);
|
|
513022
|
-
} catch (error5) {
|
|
513023
|
-
const errorDetails = formatErrorDetails2(error5, agentId);
|
|
513024
|
-
cmd.fail(`Failed: ${errorDetails}`);
|
|
513025
|
-
} finally {
|
|
513026
|
-
setCommandRunning(false);
|
|
513027
|
-
}
|
|
513028
|
-
return { submitted: true };
|
|
513029
|
-
}
|
|
513030
512620
|
if (trimmed.startsWith("/memfs")) {
|
|
513031
512621
|
const [, subcommand] = trimmed.split(/\s+/);
|
|
513032
512622
|
const cmd = commandRunner.start(msg.trim(), "Processing memfs command...");
|
|
@@ -513119,11 +512709,11 @@ Path: ${memoryDir}`, true);
|
|
|
513119
512709
|
setCommandRunning(true);
|
|
513120
512710
|
try {
|
|
513121
512711
|
const memoryDir = getScopedMemoryFilesystemRoot(agentId);
|
|
513122
|
-
if (!
|
|
512712
|
+
if (!existsSync73(memoryDir)) {
|
|
513123
512713
|
updateMemorySyncCommand(cmdId, "No local memory filesystem found to reset.", true, msg);
|
|
513124
512714
|
return { submitted: true };
|
|
513125
512715
|
}
|
|
513126
|
-
const backupDir =
|
|
512716
|
+
const backupDir = join94(tmpdir13(), `letta-memfs-reset-${agentId}-${Date.now()}`);
|
|
513127
512717
|
renameSync8(memoryDir, backupDir);
|
|
513128
512718
|
if (getBackend().capabilities.localMemfs) {
|
|
513129
512719
|
const { initializeLocalMemoryRepo: initializeLocalMemoryRepo2 } = await Promise.resolve().then(() => (init_memory_git(), exports_memory_git));
|
|
@@ -514079,7 +513669,7 @@ var init_use_submit_handler = __esm(async () => {
|
|
|
514079
513669
|
});
|
|
514080
513670
|
|
|
514081
513671
|
// src/cli/app/AppCoordinator.tsx
|
|
514082
|
-
import { join as
|
|
513672
|
+
import { join as join95 } from "node:path";
|
|
514083
513673
|
function buildStartupCommandHints(options) {
|
|
514084
513674
|
const {
|
|
514085
513675
|
isResumingConversation,
|
|
@@ -515366,7 +514956,7 @@ function App2({
|
|
|
515366
514956
|
agentId: a2.agentId ?? null
|
|
515367
514957
|
}))
|
|
515368
514958
|
});
|
|
515369
|
-
const agentModsDirectory = modContext.memfs.enabled && modContext.memfs.memoryDir ?
|
|
514959
|
+
const agentModsDirectory = modContext.memfs.enabled && modContext.memfs.memoryDir ? join95(modContext.memfs.memoryDir, "mods") : null;
|
|
515370
514960
|
const modAdapter = useLocalModAdapter(modContext, {
|
|
515371
514961
|
agentModsDirectory,
|
|
515372
514962
|
disabled: modsDisabled,
|
|
@@ -516137,9 +515727,9 @@ Memory may be stale. Try running: git -C ${getScopedMemoryFilesystemRoot(agentId
|
|
|
516137
515727
|
(async () => {
|
|
516138
515728
|
try {
|
|
516139
515729
|
const { watch: watch4 } = await import("node:fs");
|
|
516140
|
-
const { existsSync:
|
|
515730
|
+
const { existsSync: existsSync74 } = await import("node:fs");
|
|
516141
515731
|
const memRoot = getScopedMemoryFilesystemRoot(agentId);
|
|
516142
|
-
if (!
|
|
515732
|
+
if (!existsSync74(memRoot))
|
|
516143
515733
|
return;
|
|
516144
515734
|
watcher2 = watch4(memRoot, { recursive: true }, () => {});
|
|
516145
515735
|
memfsWatcherRef.current = watcher2;
|
|
@@ -517714,12 +517304,12 @@ EXAMPLES
|
|
|
517714
517304
|
console.log(usage);
|
|
517715
517305
|
}
|
|
517716
517306
|
async function printInfo() {
|
|
517717
|
-
const { join:
|
|
517307
|
+
const { join: join96 } = await import("node:path");
|
|
517718
517308
|
const { getVersion: getVersion2 } = await Promise.resolve().then(() => (init_version(), exports_version));
|
|
517719
517309
|
const { SKILLS_DIR: SKILLS_DIR2 } = await Promise.resolve().then(() => (init_skills5(), exports_skills2));
|
|
517720
517310
|
const { exists: exists2 } = await Promise.resolve().then(() => (init_fs(), exports_fs));
|
|
517721
517311
|
const cwd2 = process.cwd();
|
|
517722
|
-
const skillsDir =
|
|
517312
|
+
const skillsDir = join96(cwd2, SKILLS_DIR2);
|
|
517723
517313
|
const skillsExist = exists2(skillsDir);
|
|
517724
517314
|
await settingsManager.loadLocalProjectSettings(cwd2);
|
|
517725
517315
|
const pinned = settingsManager.getPinnedAgents();
|
|
@@ -517769,18 +517359,6 @@ async function printInfo() {
|
|
|
517769
517359
|
console.log("Pinned agents: (none)");
|
|
517770
517360
|
}
|
|
517771
517361
|
}
|
|
517772
|
-
function getModelForToolLoading(specifiedModel, specifiedToolset) {
|
|
517773
|
-
if (specifiedToolset === "codex") {
|
|
517774
|
-
return "openai/gpt-4";
|
|
517775
|
-
}
|
|
517776
|
-
if (specifiedToolset === "gemini") {
|
|
517777
|
-
return "google_ai/gemini-3.1-pro-preview";
|
|
517778
|
-
}
|
|
517779
|
-
if (specifiedToolset === "default") {
|
|
517780
|
-
return "anthropic/claude-sonnet-4";
|
|
517781
|
-
}
|
|
517782
|
-
return specifiedModel;
|
|
517783
|
-
}
|
|
517784
517362
|
function getStartupTargetLookupOrderForCredentials({
|
|
517785
517363
|
baseURL,
|
|
517786
517364
|
explicitBackendMode,
|
|
@@ -518066,10 +517644,6 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
|
|
|
518066
517644
|
process.exit(1);
|
|
518067
517645
|
}
|
|
518068
517646
|
})();
|
|
518069
|
-
const fromAfFile = resolveImportFlagAlias({
|
|
518070
|
-
importFlagValue: values4.import,
|
|
518071
|
-
fromAfFlagValue: values4["from-af"]
|
|
518072
|
-
});
|
|
518073
517647
|
const isHeadless = isHeadlessStartup(values4, process.stdin.isTTY, command);
|
|
518074
517648
|
const terminalThemePromise = !isHeadless ? initTerminalTheme().catch(() => {
|
|
518075
517649
|
return;
|
|
@@ -518151,8 +517725,8 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
|
|
|
518151
517725
|
console.error("Error: --personality can only be used with --new-agent");
|
|
518152
517726
|
process.exit(1);
|
|
518153
517727
|
}
|
|
518154
|
-
if (specifiedToolset && specifiedToolset !== "codex" && specifiedToolset !== "default" && specifiedToolset !== "gemini" && specifiedToolset !== "auto") {
|
|
518155
|
-
console.error(`Error: Invalid toolset "${specifiedToolset}". Must be "auto", "codex", "default", or "gemini".`);
|
|
517728
|
+
if (specifiedToolset && specifiedToolset !== "codex" && specifiedToolset !== "default" && specifiedToolset !== "gemini" && specifiedToolset !== "letta" && specifiedToolset !== "auto") {
|
|
517729
|
+
console.error(`Error: Invalid toolset "${specifiedToolset}". Must be "auto", "letta", "codex", "default", or "gemini".`);
|
|
518156
517730
|
process.exit(1);
|
|
518157
517731
|
}
|
|
518158
517732
|
if (systemPromptPreset && systemCustom) {
|
|
@@ -518179,7 +517753,6 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
|
|
|
518179
517753
|
specifiedAgentName,
|
|
518180
517754
|
forceNewAgent: forceNew,
|
|
518181
517755
|
forceNewConversation,
|
|
518182
|
-
importFile: fromAfFile,
|
|
518183
517756
|
shouldResume,
|
|
518184
517757
|
stateless: values4.stateless,
|
|
518185
517758
|
isHeadless,
|
|
@@ -518190,52 +517763,6 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
|
|
|
518190
517763
|
console.error(error5 instanceof Error ? `Error: ${error5.message}` : String(error5));
|
|
518191
517764
|
process.exit(1);
|
|
518192
517765
|
}
|
|
518193
|
-
let isRegistryImport = false;
|
|
518194
|
-
if (fromAfFile) {
|
|
518195
|
-
try {
|
|
518196
|
-
validateFlagConflicts({
|
|
518197
|
-
guard: fromAfFile,
|
|
518198
|
-
checks: [
|
|
518199
|
-
{
|
|
518200
|
-
when: specifiedAgentId,
|
|
518201
|
-
message: "--import cannot be used with --agent"
|
|
518202
|
-
},
|
|
518203
|
-
{
|
|
518204
|
-
when: specifiedAgentName,
|
|
518205
|
-
message: "--import cannot be used with --name"
|
|
518206
|
-
},
|
|
518207
|
-
{
|
|
518208
|
-
when: shouldResume,
|
|
518209
|
-
message: "--import cannot be used with --resume"
|
|
518210
|
-
},
|
|
518211
|
-
{
|
|
518212
|
-
when: forceNew,
|
|
518213
|
-
message: "--import cannot be used with --new-agent"
|
|
518214
|
-
}
|
|
518215
|
-
]
|
|
518216
|
-
});
|
|
518217
|
-
} catch (error5) {
|
|
518218
|
-
console.error(error5 instanceof Error ? `Error: ${error5.message}` : String(error5));
|
|
518219
|
-
process.exit(1);
|
|
518220
|
-
}
|
|
518221
|
-
if (fromAfFile.startsWith("@")) {
|
|
518222
|
-
isRegistryImport = true;
|
|
518223
|
-
try {
|
|
518224
|
-
validateRegistryHandleOrThrow(fromAfFile);
|
|
518225
|
-
} catch {
|
|
518226
|
-
console.error(`Error: Invalid registry handle "${fromAfFile}". Use format: letta --import @author/agentname`);
|
|
518227
|
-
process.exit(1);
|
|
518228
|
-
}
|
|
518229
|
-
} else {
|
|
518230
|
-
const { resolve: resolve45 } = await import("node:path");
|
|
518231
|
-
const { existsSync: existsSync75 } = await import("node:fs");
|
|
518232
|
-
const resolvedPath = resolve45(fromAfFile);
|
|
518233
|
-
if (!existsSync75(resolvedPath)) {
|
|
518234
|
-
console.error(`Error: AgentFile not found: ${resolvedPath}`);
|
|
518235
|
-
process.exit(1);
|
|
518236
|
-
}
|
|
518237
|
-
}
|
|
518238
|
-
}
|
|
518239
517766
|
let nameResolvedAgent = null;
|
|
518240
517767
|
if (specifiedAgentName) {
|
|
518241
517768
|
if (specifiedAgentId) {
|
|
@@ -518417,8 +517944,11 @@ Error: ${message}`);
|
|
|
518417
517944
|
}
|
|
518418
517945
|
if (isHeadless) {
|
|
518419
517946
|
markMilestone("HEADLESS_MODE_START");
|
|
518420
|
-
|
|
518421
|
-
|
|
517947
|
+
await loadStartupTools({
|
|
517948
|
+
modelIdentifier: specifiedModel,
|
|
517949
|
+
toolset: specifiedToolset,
|
|
517950
|
+
exclude: ["AskUserQuestion"]
|
|
517951
|
+
});
|
|
518422
517952
|
markMilestone("TOOLS_LOADED");
|
|
518423
517953
|
const headlessValues = specifiedAgentId && values4.agent !== specifiedAgentId ? { ...values4, agent: specifiedAgentId } : values4;
|
|
518424
517954
|
const { handleHeadlessCommand: handleHeadlessCommand2 } = await init_headless().then(() => exports_headless);
|
|
@@ -518445,9 +517975,7 @@ Error: ${message}`);
|
|
|
518445
517975
|
model,
|
|
518446
517976
|
systemPromptPreset: systemPromptPreset2,
|
|
518447
517977
|
toolset,
|
|
518448
|
-
skillsDirectory: skillsDirectory2
|
|
518449
|
-
fromAfFile: fromAfFile2,
|
|
518450
|
-
isRegistryImport: isRegistryImport2
|
|
517978
|
+
skillsDirectory: skillsDirectory2
|
|
518451
517979
|
}) {
|
|
518452
517980
|
const [showKeybindingSetup, setShowKeybindingSetup] = useState56(null);
|
|
518453
517981
|
const [loadingState, setLoadingState] = useState56("selecting");
|
|
@@ -518635,8 +518163,8 @@ Error: ${message}`);
|
|
|
518635
518163
|
console.error("Run 'letta' to get started.");
|
|
518636
518164
|
process.exit(1);
|
|
518637
518165
|
}
|
|
518638
|
-
if (forceNew2 || agentIdArg
|
|
518639
|
-
if (agentIdArg && !forceNew2 && !
|
|
518166
|
+
if (forceNew2 || agentIdArg) {
|
|
518167
|
+
if (agentIdArg && !forceNew2 && !forceNewConversation) {
|
|
518640
518168
|
await settingsManager.loadLocalProjectSettings(process.cwd());
|
|
518641
518169
|
const localSession2 = settingsManager.getLocalLastSession(process.cwd());
|
|
518642
518170
|
if (localSession2?.agentId === agentIdArg && localSession2.conversationId && localSession2.conversationId !== "default") {
|
|
@@ -518743,13 +518271,7 @@ Error: ${message}`);
|
|
|
518743
518271
|
setLoadingState("assembling");
|
|
518744
518272
|
}
|
|
518745
518273
|
checkAndStart();
|
|
518746
|
-
}, [
|
|
518747
|
-
forceNew2,
|
|
518748
|
-
agentIdArg,
|
|
518749
|
-
fromAfFile2,
|
|
518750
|
-
shouldResume,
|
|
518751
|
-
specifiedConversationId
|
|
518752
|
-
]);
|
|
518274
|
+
}, [forceNew2, agentIdArg, shouldResume, specifiedConversationId]);
|
|
518753
518275
|
const initStartedRef = React14.useRef(false);
|
|
518754
518276
|
useEffect50(() => {
|
|
518755
518277
|
if (loadingState !== "assembling") {
|
|
@@ -518820,48 +518342,11 @@ Error: ${message}`);
|
|
|
518820
518342
|
}
|
|
518821
518343
|
}
|
|
518822
518344
|
setIsResumingSession(!!resumingAgentId);
|
|
518823
|
-
|
|
518824
|
-
await loadTools(modelForTools);
|
|
518345
|
+
await loadStartupTools({ modelIdentifier: model, toolset });
|
|
518825
518346
|
setLoadingState("initializing");
|
|
518826
518347
|
const { createAgent: createAgent2 } = await Promise.resolve().then(() => (init_create5(), exports_create));
|
|
518827
518348
|
let agent = null;
|
|
518828
518349
|
let autoEnableMemfsForFreshAgent = false;
|
|
518829
|
-
if (fromAfFile2) {
|
|
518830
|
-
setLoadingState("importing");
|
|
518831
|
-
let result2;
|
|
518832
|
-
if (isRegistryImport2) {
|
|
518833
|
-
const { importAgentFromRegistry: importAgentFromRegistry2 } = await Promise.resolve().then(() => (init_import(), exports_import));
|
|
518834
|
-
result2 = await importAgentFromRegistry2({
|
|
518835
|
-
handle: fromAfFile2,
|
|
518836
|
-
modelOverride: model,
|
|
518837
|
-
stripMessages: true,
|
|
518838
|
-
stripSkills: false
|
|
518839
|
-
});
|
|
518840
|
-
} else {
|
|
518841
|
-
const { importAgentFromFile: importAgentFromFile2 } = await Promise.resolve().then(() => (init_import(), exports_import));
|
|
518842
|
-
result2 = await importAgentFromFile2({
|
|
518843
|
-
filePath: fromAfFile2,
|
|
518844
|
-
modelOverride: model,
|
|
518845
|
-
stripMessages: true,
|
|
518846
|
-
stripSkills: false
|
|
518847
|
-
});
|
|
518848
|
-
}
|
|
518849
|
-
agent = result2.agent;
|
|
518850
|
-
setAgentProvenance({
|
|
518851
|
-
isNew: true,
|
|
518852
|
-
blocks: []
|
|
518853
|
-
});
|
|
518854
|
-
if (settingsManager.isReady) {
|
|
518855
|
-
settingsManager.setSystemPromptCustom(agent.id);
|
|
518856
|
-
}
|
|
518857
|
-
if (result2.skills && result2.skills.length > 0) {
|
|
518858
|
-
const { getAgentSkillsDir: getAgentSkillsDir2 } = await Promise.resolve().then(() => (init_skills5(), exports_skills2));
|
|
518859
|
-
const skillsDir = getAgentSkillsDir2(agent.id);
|
|
518860
|
-
console.log(`
|
|
518861
|
-
\uD83D\uDCE6 Extracted ${result2.skills.length} skill${result2.skills.length === 1 ? "" : "s"} to ${skillsDir}: ${result2.skills.join(", ")}
|
|
518862
|
-
`);
|
|
518863
|
-
}
|
|
518864
|
-
}
|
|
518865
518350
|
if (!agent && agentIdArg) {
|
|
518866
518351
|
try {
|
|
518867
518352
|
agent = await backend3.retrieveAgent(agentIdArg, {
|
|
@@ -518969,7 +518454,7 @@ Error: ${message}`);
|
|
|
518969
518454
|
if (!shouldBlockOnMemfsStartup) {}
|
|
518970
518455
|
const secretsInitPromise = Promise.resolve().then(() => (init_secrets_store(), exports_secrets_store)).then(({ initSecretsFromServer: initSecretsFromServer2 }) => initSecretsFromServer2(agentId2));
|
|
518971
518456
|
const isResumingProject = !shouldCreateNew && !!resumingAgentId;
|
|
518972
|
-
const isReusingExistingAgent = !shouldCreateNew &&
|
|
518457
|
+
const isReusingExistingAgent = !shouldCreateNew && agent && agent.id;
|
|
518973
518458
|
const resuming = !!(agentIdArg || isResumingProject || isReusingExistingAgent);
|
|
518974
518459
|
setIsResumingSession(resuming);
|
|
518975
518460
|
if (resuming) {
|
|
@@ -519129,7 +518614,6 @@ Error during initialization: ${message}`);
|
|
|
519129
518614
|
agentIdArg,
|
|
519130
518615
|
model,
|
|
519131
518616
|
systemPromptPreset2,
|
|
519132
|
-
fromAfFile2,
|
|
519133
518617
|
loadingState,
|
|
519134
518618
|
selectedGlobalAgentId,
|
|
519135
518619
|
validatedAgent,
|
|
@@ -519253,15 +518737,14 @@ Error during initialization: ${message}`);
|
|
|
519253
518737
|
model: specifiedModel,
|
|
519254
518738
|
systemPromptPreset,
|
|
519255
518739
|
toolset: specifiedToolset,
|
|
519256
|
-
skillsDirectory
|
|
519257
|
-
fromAfFile,
|
|
519258
|
-
isRegistryImport
|
|
518740
|
+
skillsDirectory
|
|
519259
518741
|
}), {
|
|
519260
518742
|
exitOnCtrlC: false
|
|
519261
518743
|
});
|
|
519262
518744
|
}
|
|
519263
518745
|
var EMPTY_APPROVAL_ARRAY, EMPTY_MESSAGE_ARRAY;
|
|
519264
518746
|
var init_src5 = __esm(async () => {
|
|
518747
|
+
init_startup_log_boundary();
|
|
519265
518748
|
init_error();
|
|
519266
518749
|
init_telemetry();
|
|
519267
518750
|
init_error_reporting();
|
|
@@ -519293,7 +518776,7 @@ var init_src5 = __esm(async () => {
|
|
|
519293
518776
|
init_ConversationSelector(),
|
|
519294
518777
|
init_profile_selection(),
|
|
519295
518778
|
init_router(),
|
|
519296
|
-
|
|
518779
|
+
init_letta_toolset(),
|
|
519297
518780
|
init_toolset()
|
|
519298
518781
|
]);
|
|
519299
518782
|
EMPTY_APPROVAL_ARRAY = [];
|
|
@@ -519301,6 +518784,9 @@ var init_src5 = __esm(async () => {
|
|
|
519301
518784
|
assertSupportedBunRuntime();
|
|
519302
518785
|
main2();
|
|
519303
518786
|
});
|
|
518787
|
+
|
|
518788
|
+
// src/standalone-entry.ts
|
|
518789
|
+
init_startup_log_boundary();
|
|
519304
518790
|
// node_modules/@earendil-works/pi-ai/dist/auth/oauth/oauth-page.js
|
|
519305
518791
|
var LOGO_SVG = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 800" aria-hidden="true"><path fill="#fff" fill-rule="evenodd" d="M165.29 165.29 H517.36 V400 H400 V517.36 H282.65 V634.72 H165.29 Z M282.65 282.65 V400 H400 V282.65 Z"/><path fill="#fff" d="M517.36 400 H634.72 V634.72 H517.36 Z"/></svg>`;
|
|
519306
518792
|
function escapeHtml(value) {
|
|
@@ -521496,4 +520982,4 @@ function registerBunOAuthFlows() {
|
|
|
521496
520982
|
registerBunOAuthFlows();
|
|
521497
520983
|
await init_src5().then(() => exports_src2);
|
|
521498
520984
|
|
|
521499
|
-
//# debugId=
|
|
520985
|
+
//# debugId=95B2BCB7592A39B564756E2164756E21
|