ai-sdk-letta 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/LICENSE +202 -0
- package/NOTICE +9 -0
- package/README.md +35 -0
- package/dist/agent.d.ts +108 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +371 -0
- package/dist/agent.js.map +1 -0
- package/dist/definition.d.ts +81 -0
- package/dist/definition.d.ts.map +1 -0
- package/dist/definition.js +87 -0
- package/dist/definition.js.map +1 -0
- package/dist/history.d.ts +38 -0
- package/dist/history.d.ts.map +1 -0
- package/dist/history.js +226 -0
- package/dist/history.js.map +1 -0
- package/dist/identity.d.ts +43 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +158 -0
- package/dist/identity.js.map +1 -0
- package/dist/images.d.ts +83 -0
- package/dist/images.d.ts.map +1 -0
- package/dist/images.js +181 -0
- package/dist/images.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/interactions.d.ts +61 -0
- package/dist/interactions.d.ts.map +1 -0
- package/dist/interactions.js +110 -0
- package/dist/interactions.js.map +1 -0
- package/dist/memory.d.ts +11 -0
- package/dist/memory.d.ts.map +1 -0
- package/dist/memory.js +55 -0
- package/dist/memory.js.map +1 -0
- package/dist/navigation.d.ts +50 -0
- package/dist/navigation.d.ts.map +1 -0
- package/dist/navigation.js +87 -0
- package/dist/navigation.js.map +1 -0
- package/dist/runtime.d.ts +83 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +246 -0
- package/dist/runtime.js.map +1 -0
- package/dist/state.d.ts +24 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/state.js +39 -0
- package/dist/state.js.map +1 -0
- package/dist/tools.d.ts +83 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +162 -0
- package/dist/tools.js.map +1 -0
- package/package.json +67 -0
- package/src/agent.ts +334 -0
- package/src/definition.ts +136 -0
- package/src/history.ts +198 -0
- package/src/identity.ts +125 -0
- package/src/images.ts +184 -0
- package/src/index.ts +23 -0
- package/src/interactions.ts +121 -0
- package/src/memory.ts +42 -0
- package/src/navigation.ts +84 -0
- package/src/runtime.ts +243 -0
- package/src/state.ts +39 -0
- package/src/tools.ts +166 -0
package/dist/images.js
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
/** Image types a user turn may carry. Letta's `ImageContent` accepts exactly these. */
|
|
3
|
+
export const IMAGE_MEDIA_TYPES = ['image/png', 'image/jpeg', 'image/gif', 'image/webp'];
|
|
4
|
+
export const IMAGE_LIMITS = Object.freeze({
|
|
5
|
+
/** Largest single image. */
|
|
6
|
+
maxImageBytes: 5 * 1024 * 1024,
|
|
7
|
+
/** Most images in one user turn. */
|
|
8
|
+
maxImages: 4,
|
|
9
|
+
/** Largest combined size of all images in one user turn. */
|
|
10
|
+
maxTotalBytes: 10 * 1024 * 1024,
|
|
11
|
+
});
|
|
12
|
+
/** A rejected image input. `code` is stable; `message` is human-readable. */
|
|
13
|
+
export class ImageInputError extends Error {
|
|
14
|
+
code;
|
|
15
|
+
name = 'ImageInputError';
|
|
16
|
+
constructor(code, message) {
|
|
17
|
+
super(message);
|
|
18
|
+
this.code = code;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
const MB = (bytes) => `${Math.round(bytes / 1024 / 1024)} MB`;
|
|
22
|
+
const base64Pattern = /^[A-Za-z0-9+/]*={0,2}$/;
|
|
23
|
+
/** Reference provider key used for images in the in-memory transcript. */
|
|
24
|
+
export const IMAGE_REFERENCE_PROVIDER = 'ai-sdk-letta-sha256';
|
|
25
|
+
/** Detect PNG, JPEG, GIF or WebP from magic bytes; `undefined` otherwise. */
|
|
26
|
+
export function sniffImageType(bytes) {
|
|
27
|
+
const at = (offset, ...values) => values.every((value, index) => bytes[offset + index] === value);
|
|
28
|
+
if (at(0, 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a))
|
|
29
|
+
return 'image/png';
|
|
30
|
+
if (at(0, 0xff, 0xd8, 0xff))
|
|
31
|
+
return 'image/jpeg';
|
|
32
|
+
if (at(0, 0x47, 0x49, 0x46, 0x38) && (bytes[4] === 0x37 || bytes[4] === 0x39) && bytes[5] === 0x61)
|
|
33
|
+
return 'image/gif';
|
|
34
|
+
if (at(0, 0x52, 0x49, 0x46, 0x46) && at(8, 0x57, 0x45, 0x42, 0x50))
|
|
35
|
+
return 'image/webp';
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
/** Normalize a declared media type: `image/jpg` → `image/jpeg`, parameters and case dropped; `image`/`image/*` mean "detect". */
|
|
39
|
+
function declaredType(mediaType) {
|
|
40
|
+
if (mediaType === undefined)
|
|
41
|
+
return 'detect';
|
|
42
|
+
if (typeof mediaType !== 'string')
|
|
43
|
+
throw new ImageInputError('image_unsupported_type', 'Image media type must be a string');
|
|
44
|
+
const type = mediaType.split(';', 1)[0].trim().toLowerCase();
|
|
45
|
+
if (type === 'image' || type === 'image/*')
|
|
46
|
+
return 'detect';
|
|
47
|
+
const normalized = type === 'image/jpg' ? 'image/jpeg' : type;
|
|
48
|
+
if (!IMAGE_MEDIA_TYPES.includes(normalized))
|
|
49
|
+
throw new ImageInputError('image_unsupported_type', `Unsupported image type ${type || 'unknown'}; use PNG, JPEG, GIF or WebP`);
|
|
50
|
+
return normalized;
|
|
51
|
+
}
|
|
52
|
+
function fromBase64(base64, declared, limit) {
|
|
53
|
+
const clean = base64.replace(/\s+/g, '');
|
|
54
|
+
if (!clean || clean.length % 4 === 1 || !base64Pattern.test(clean))
|
|
55
|
+
throw new ImageInputError('image_invalid', 'Image data is not valid base64');
|
|
56
|
+
// Cheap bound before decoding anything large.
|
|
57
|
+
if (Math.floor(clean.length * 3 / 4) - 2 > limit)
|
|
58
|
+
throw new ImageInputError('image_too_large', `Each image can be up to ${MB(limit)}`);
|
|
59
|
+
const buffer = Buffer.from(clean, 'base64');
|
|
60
|
+
return fromBytes(buffer, declared, limit, clean);
|
|
61
|
+
}
|
|
62
|
+
function fromBytes(bytes, declared, limit, base64) {
|
|
63
|
+
if (!bytes.byteLength)
|
|
64
|
+
throw new ImageInputError('image_invalid', 'Image is empty');
|
|
65
|
+
if (bytes.byteLength > limit)
|
|
66
|
+
throw new ImageInputError('image_too_large', `Each image can be up to ${MB(limit)}`);
|
|
67
|
+
const sniffed = sniffImageType(bytes);
|
|
68
|
+
if (!sniffed)
|
|
69
|
+
throw new ImageInputError(declared === 'detect' ? 'image_unsupported_type' : 'image_invalid', declared === 'detect' ? 'Unsupported image; use PNG, JPEG, GIF or WebP' : `Image content is not a valid ${declared.slice(6).toUpperCase()}`);
|
|
70
|
+
if (declared !== 'detect' && declared !== sniffed)
|
|
71
|
+
throw new ImageInputError('image_invalid', `Image content (${sniffed}) does not match its declared type (${declared})`);
|
|
72
|
+
const data = base64 ?? Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength).toString('base64');
|
|
73
|
+
return { mediaType: sniffed, base64: data, bytes: bytes.byteLength, sha256: createHash('sha256').update(bytes).digest('hex') };
|
|
74
|
+
}
|
|
75
|
+
/** Parse a `data:` URL (base64 only). */
|
|
76
|
+
function fromDataUrl(url, declared, limit) {
|
|
77
|
+
const match = /^data:([^,;]*)((?:;[^,;]*)*),(.*)$/s.exec(url);
|
|
78
|
+
if (!match || !match[2].split(';').includes('base64'))
|
|
79
|
+
throw new ImageInputError('image_invalid', 'Image data URLs must be base64-encoded');
|
|
80
|
+
const urlType = match[1] ? declaredType(match[1]) : 'detect';
|
|
81
|
+
if (declared !== 'detect' && urlType !== 'detect' && urlType !== declared)
|
|
82
|
+
throw new ImageInputError('image_invalid', 'Image data URL type does not match the declared type');
|
|
83
|
+
return fromBase64(match[3], declared === 'detect' ? urlType : declared, limit);
|
|
84
|
+
}
|
|
85
|
+
/** The reference hash in a compact transcript part, if this part is one. */
|
|
86
|
+
function referenceOf(value) {
|
|
87
|
+
const pick = (v) => {
|
|
88
|
+
const ref = v && typeof v === 'object' && !(v instanceof Uint8Array) && !(v instanceof ArrayBuffer) && !(v instanceof URL) ? v[IMAGE_REFERENCE_PROVIDER] : undefined;
|
|
89
|
+
return typeof ref === 'string' && /^[a-f0-9]{64}$/.test(ref) ? ref : undefined;
|
|
90
|
+
};
|
|
91
|
+
if (value && typeof value === 'object' && value.type === 'reference')
|
|
92
|
+
return pick(value.reference);
|
|
93
|
+
return pick(value);
|
|
94
|
+
}
|
|
95
|
+
/** True for AI SDK `image` parts and `file` parts whose media type is an image. */
|
|
96
|
+
export function isImagePart(part) {
|
|
97
|
+
if (part.type === 'image')
|
|
98
|
+
return true;
|
|
99
|
+
return part.type === 'file' && typeof part.mediaType === 'string' && /^image(?:\/|$)/i.test(part.mediaType.trim());
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Validate one AI SDK `image` or `file` part and decode it. Accepts base64
|
|
103
|
+
* strings, `data:` URLs (string or `URL`), bytes, and the tagged
|
|
104
|
+
* `{ type: 'data' | 'url' }` file shapes. Remote URLs are rejected: images are
|
|
105
|
+
* never fetched.
|
|
106
|
+
* @throws {ImageInputError}
|
|
107
|
+
*/
|
|
108
|
+
export function decodeImagePart(part, limit = IMAGE_LIMITS.maxImageBytes) {
|
|
109
|
+
const declared = declaredType(part.mediaType);
|
|
110
|
+
let value = part.type === 'image' ? part.image : part.data;
|
|
111
|
+
if (value && typeof value === 'object' && !(value instanceof Uint8Array) && !(value instanceof ArrayBuffer) && !(value instanceof URL)) {
|
|
112
|
+
const tagged = value;
|
|
113
|
+
if (tagged.type === 'data')
|
|
114
|
+
value = tagged.data;
|
|
115
|
+
else if (tagged.type === 'url')
|
|
116
|
+
value = tagged.url;
|
|
117
|
+
else
|
|
118
|
+
throw new ImageInputError('image_invalid', 'Provider file references and inline text are not supported for images');
|
|
119
|
+
}
|
|
120
|
+
if (value instanceof URL)
|
|
121
|
+
value = value.href;
|
|
122
|
+
if (typeof value === 'string') {
|
|
123
|
+
if (/^data:/i.test(value))
|
|
124
|
+
return fromDataUrl(value, declared, limit);
|
|
125
|
+
// Base64 never contains ':'; anything with a scheme is a URL we will not fetch.
|
|
126
|
+
if (/^[a-z][a-z0-9+.-]*:/i.test(value.trimStart()))
|
|
127
|
+
throw new ImageInputError('image_remote_url', 'Image URLs are not fetched; attach the image data instead');
|
|
128
|
+
return fromBase64(value, declared, limit);
|
|
129
|
+
}
|
|
130
|
+
if (value instanceof ArrayBuffer)
|
|
131
|
+
return fromBytes(new Uint8Array(value), declared, limit);
|
|
132
|
+
if (value instanceof Uint8Array)
|
|
133
|
+
return fromBytes(value, declared, limit);
|
|
134
|
+
throw new ImageInputError('image_invalid', 'Unsupported image data');
|
|
135
|
+
}
|
|
136
|
+
/** Enforce count and combined size over already-decoded images. @throws {ImageInputError} */
|
|
137
|
+
export function assertImageBudget(images, limits = IMAGE_LIMITS) {
|
|
138
|
+
if (images.length > limits.maxImages)
|
|
139
|
+
throw new ImageInputError('images_too_many', `Attach up to ${limits.maxImages} images per message`);
|
|
140
|
+
const total = images.reduce((sum, image) => sum + image.bytes, 0);
|
|
141
|
+
if (total > limits.maxTotalBytes)
|
|
142
|
+
throw new ImageInputError('images_too_large', `Images in one message can total up to ${MB(limits.maxTotalBytes)}`);
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Validate a list of base64 images (as received over HTTP) against every
|
|
146
|
+
* limit. Returns decoded images with their content hash.
|
|
147
|
+
* @throws {ImageInputError}
|
|
148
|
+
*/
|
|
149
|
+
export function validateImages(images, limits = IMAGE_LIMITS) {
|
|
150
|
+
if (!Array.isArray(images))
|
|
151
|
+
throw new ImageInputError('image_invalid', 'Images must be a list');
|
|
152
|
+
if (images.length > limits.maxImages)
|
|
153
|
+
throw new ImageInputError('images_too_many', `Attach up to ${limits.maxImages} images per message`);
|
|
154
|
+
const decoded = images.map(image => {
|
|
155
|
+
if (!image || typeof image !== 'object' || typeof image.data !== 'string')
|
|
156
|
+
throw new ImageInputError('image_invalid', 'Each image needs base64 data');
|
|
157
|
+
return decodeImagePart({ type: 'image', image: image.data, mediaType: image.mediaType }, limits.maxImageBytes);
|
|
158
|
+
});
|
|
159
|
+
assertImageBudget(decoded, limits);
|
|
160
|
+
return decoded;
|
|
161
|
+
}
|
|
162
|
+
/** Letta `ImageContent` for a decoded image. */
|
|
163
|
+
export const toLettaImage = (image) => ({ type: 'image', source: { type: 'base64', media_type: image.mediaType, data: image.base64 } });
|
|
164
|
+
/**
|
|
165
|
+
* Content hash of an image part, for history comparison. Compact transcript
|
|
166
|
+
* references (see {@link compactImagePart}) yield their stored hash; anything
|
|
167
|
+
* else is decoded and hashed.
|
|
168
|
+
*/
|
|
169
|
+
export function imagePartDigest(part) {
|
|
170
|
+
return referenceOf(part.type === 'image' ? part.image : part.data) ?? decodeImagePart(part, Number.MAX_SAFE_INTEGER).sha256;
|
|
171
|
+
}
|
|
172
|
+
/** Replace an image part's data with a content-hash reference, so transcripts never hold image bytes twice. */
|
|
173
|
+
export function compactImagePart(part) {
|
|
174
|
+
const existing = referenceOf(part.type === 'image' ? part.image : part.data);
|
|
175
|
+
const mediaType = typeof part.mediaType === 'string' && part.mediaType.includes('/') ? part.mediaType : 'image';
|
|
176
|
+
if (existing)
|
|
177
|
+
return { type: 'file', mediaType, data: { type: 'reference', reference: { [IMAGE_REFERENCE_PROVIDER]: existing } } };
|
|
178
|
+
const image = decodeImagePart(part, Number.MAX_SAFE_INTEGER);
|
|
179
|
+
return { type: 'file', mediaType: image.mediaType, data: { type: 'reference', reference: { [IMAGE_REFERENCE_PROVIDER]: image.sha256 } } };
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=images.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"images.js","sourceRoot":"","sources":["../src/images.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ai-sdk-letta: a persistent, Letta-backed Vercel AI SDK `Agent` with
|
|
3
|
+
* application-owned tools and human-in-the-loop interactions.
|
|
4
|
+
*
|
|
5
|
+
* @packageDocumentation
|
|
6
|
+
*/
|
|
7
|
+
export { LettaAgent, historyKey, userTurnContent, MAX_INPUT_CHARACTERS, type LettaAgentOptions, type AgentPresentation, type DeliveryHooks, type TurnSession } from './agent.js';
|
|
8
|
+
export { IMAGE_LIMITS, IMAGE_MEDIA_TYPES, IMAGE_REFERENCE_PROVIDER, ImageInputError, validateImages, decodeImagePart, assertImageBudget, isImagePart, sniffImageType, toLettaImage, imagePartDigest, compactImagePart, type ImageInputErrorCode, type ImageMediaType, type ImageLimits, type DecodedImage, } from './images.js';
|
|
9
|
+
export { defineAgent, creationOptions, dreamingCommand, memoryPolicyInstructions, DEFAULT_DREAMING, INTERNAL_MEMORY_TOOLS, type AgentDefinition, type AgentDefinitionInput, type DreamingSettings, type DreamingTrigger, type ToolPermission, } from './definition.js';
|
|
10
|
+
export { openLettaAgent, createLettaAgent, assertIdle, sessionOptions, foregroundToolsCommand, localBackendDirectory, type OpenAgentOptions, type LettaRuntime, type ConversationChoice } from './runtime.js';
|
|
11
|
+
export { acquireIdentity, validConversationId, type Identity, type IdentityBackend, type IdentityLease } from './identity.js';
|
|
12
|
+
export { HISTORY_LIMIT, HISTORY_IMAGE_BUDGET, IMAGE_PLACEHOLDER, sanitizeText, historyPage, loadHistory, projectHistory, assertHistorySettled, listConversations } from './history.js';
|
|
13
|
+
export { listNavigationEntries, searchConversations, snippet, SEARCH_CONVERSATIONS, SEARCH_RECORDS, SEARCH_TOTAL, SEARCH_MATCHES, SEARCH_MILLISECONDS, type ConversationEntry, type NavigationSource, type SearchMatch } from './navigation.js';
|
|
14
|
+
export { ToolInteractions, validateQuestion, validateResponse, type Question, type InteractionRequest, type InteractionResponse, type InteractionHandler } from './interactions.js';
|
|
15
|
+
export { createToolBridge, askUserTool, fileTraceWriter, ASK_USER_TOOL, type AskUserResult, type ToolActivity, type ToolBridge, type ToolBridgeOptions } from './tools.js';
|
|
16
|
+
export { allowMemoryTool, memoryCommitCommand } from './memory.js';
|
|
17
|
+
export { resolveStateDirectory, statePaths, STATE_DIR_ENV } from './state.js';
|
|
18
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,eAAe,EAAE,oBAAoB,EAAE,KAAK,iBAAiB,EAAE,KAAK,iBAAiB,EAAE,KAAK,aAAa,EAAE,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AACjL,OAAO,EACL,YAAY,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,EAAE,iBAAiB,EAAE,WAAW,EAAE,cAAc,EAAE,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAC5M,KAAK,mBAAmB,EAAE,KAAK,cAAc,EAAE,KAAK,WAAW,EAAE,KAAK,YAAY,GACnF,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,WAAW,EAAE,eAAe,EAAE,eAAe,EAAE,wBAAwB,EAAE,gBAAgB,EAAE,qBAAqB,EAChH,KAAK,eAAe,EAAE,KAAK,oBAAoB,EAAE,KAAK,gBAAgB,EAAE,KAAK,eAAe,EAAE,KAAK,cAAc,GAClH,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,UAAU,EAAE,cAAc,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,KAAK,gBAAgB,EAAE,KAAK,YAAY,EAAE,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAC9M,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,KAAK,QAAQ,EAAE,KAAK,eAAe,EAAE,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9H,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACvL,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,YAAY,EAAE,cAAc,EAAE,mBAAmB,EAAE,KAAK,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAChP,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,KAAK,QAAQ,EAAE,KAAK,kBAAkB,EAAE,KAAK,mBAAmB,EAAE,KAAK,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACpL,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,eAAe,EAAE,aAAa,EAAE,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,KAAK,UAAU,EAAE,KAAK,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC3K,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,qBAAqB,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ai-sdk-letta: a persistent, Letta-backed Vercel AI SDK `Agent` with
|
|
3
|
+
* application-owned tools and human-in-the-loop interactions.
|
|
4
|
+
*
|
|
5
|
+
* @packageDocumentation
|
|
6
|
+
*/
|
|
7
|
+
export { LettaAgent, historyKey, userTurnContent, MAX_INPUT_CHARACTERS } from './agent.js';
|
|
8
|
+
export { IMAGE_LIMITS, IMAGE_MEDIA_TYPES, IMAGE_REFERENCE_PROVIDER, ImageInputError, validateImages, decodeImagePart, assertImageBudget, isImagePart, sniffImageType, toLettaImage, imagePartDigest, compactImagePart, } from './images.js';
|
|
9
|
+
export { defineAgent, creationOptions, dreamingCommand, memoryPolicyInstructions, DEFAULT_DREAMING, INTERNAL_MEMORY_TOOLS, } from './definition.js';
|
|
10
|
+
export { openLettaAgent, createLettaAgent, assertIdle, sessionOptions, foregroundToolsCommand, localBackendDirectory } from './runtime.js';
|
|
11
|
+
export { acquireIdentity, validConversationId } from './identity.js';
|
|
12
|
+
export { HISTORY_LIMIT, HISTORY_IMAGE_BUDGET, IMAGE_PLACEHOLDER, sanitizeText, historyPage, loadHistory, projectHistory, assertHistorySettled, listConversations } from './history.js';
|
|
13
|
+
export { listNavigationEntries, searchConversations, snippet, SEARCH_CONVERSATIONS, SEARCH_RECORDS, SEARCH_TOTAL, SEARCH_MATCHES, SEARCH_MILLISECONDS } from './navigation.js';
|
|
14
|
+
export { ToolInteractions, validateQuestion, validateResponse } from './interactions.js';
|
|
15
|
+
export { createToolBridge, askUserTool, fileTraceWriter, ASK_USER_TOOL } from './tools.js';
|
|
16
|
+
export { allowMemoryTool, memoryCommitCommand } from './memory.js';
|
|
17
|
+
export { resolveStateDirectory, statePaths, STATE_DIR_ENV } from './state.js';
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,eAAe,EAAE,oBAAoB,EAAwF,MAAM,YAAY,CAAC;AACjL,OAAO,EACL,YAAY,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,EAAE,iBAAiB,EAAE,WAAW,EAAE,cAAc,EAAE,YAAY,EAAE,eAAe,EAAE,gBAAgB,GAE7M,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,WAAW,EAAE,eAAe,EAAE,eAAe,EAAE,wBAAwB,EAAE,gBAAgB,EAAE,qBAAqB,GAEjH,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,UAAU,EAAE,cAAc,EAAE,sBAAsB,EAAE,qBAAqB,EAAqE,MAAM,cAAc,CAAC;AAC9M,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAA2D,MAAM,eAAe,CAAC;AAC9H,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACvL,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,YAAY,EAAE,cAAc,EAAE,mBAAmB,EAAmE,MAAM,iBAAiB,CAAC;AAChP,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,gBAAgB,EAA6F,MAAM,mBAAmB,CAAC;AACpL,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,eAAe,EAAE,aAAa,EAAkF,MAAM,YAAY,CAAC;AAC3K,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,qBAAqB,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/** Arguments of the built-in `ask_user` tool. */
|
|
2
|
+
export type Question = {
|
|
3
|
+
question: string;
|
|
4
|
+
options?: {
|
|
5
|
+
id: string;
|
|
6
|
+
label: string;
|
|
7
|
+
}[];
|
|
8
|
+
allowFreeText?: boolean;
|
|
9
|
+
multiSelect?: boolean;
|
|
10
|
+
};
|
|
11
|
+
/** A prompt the application must show to a human: approve a tool call, or answer a question. */
|
|
12
|
+
export type InteractionRequest = {
|
|
13
|
+
/** Unique per prompt; a response must echo it. */
|
|
14
|
+
id: string;
|
|
15
|
+
toolCallId: string;
|
|
16
|
+
tool: string;
|
|
17
|
+
kind: 'approval' | 'question';
|
|
18
|
+
title: string;
|
|
19
|
+
/** For approvals: the exact JSON arguments that will run if approved. */
|
|
20
|
+
details?: string;
|
|
21
|
+
options?: Question['options'];
|
|
22
|
+
allowFreeText?: boolean;
|
|
23
|
+
multiSelect?: boolean;
|
|
24
|
+
};
|
|
25
|
+
/** A human's answer. Approvals use `approved`; questions use `selected` and/or `text`. */
|
|
26
|
+
export type InteractionResponse = {
|
|
27
|
+
id: string;
|
|
28
|
+
approved?: boolean;
|
|
29
|
+
cancelled?: boolean;
|
|
30
|
+
selected?: string[];
|
|
31
|
+
text?: string;
|
|
32
|
+
};
|
|
33
|
+
/** Renders one request and resolves with the human's response. `signal` aborts when the prompt is withdrawn. */
|
|
34
|
+
export type InteractionHandler = (request: InteractionRequest, signal: AbortSignal) => Promise<unknown>;
|
|
35
|
+
/**
|
|
36
|
+
* Interaction broker: serializes human prompts (FIFO, one at a time) between
|
|
37
|
+
* tool calls and a single connected renderer (TUI, GUI, or your own).
|
|
38
|
+
*
|
|
39
|
+
* Responses are validated against the exact request and are never interpreted
|
|
40
|
+
* as chat turns. Without a connected renderer, requests fail closed.
|
|
41
|
+
*/
|
|
42
|
+
export declare class ToolInteractions {
|
|
43
|
+
private handler?;
|
|
44
|
+
private queue;
|
|
45
|
+
private active?;
|
|
46
|
+
private closed;
|
|
47
|
+
/** Attach the renderer. Returns a disconnect function that cancels all pending prompts. */
|
|
48
|
+
readonly connect: (handler: InteractionHandler) => (() => void);
|
|
49
|
+
/** Permanently close the broker and cancel every pending prompt. */
|
|
50
|
+
close(): void;
|
|
51
|
+
private cancelAll;
|
|
52
|
+
/** Queue a prompt. Rejects with `interaction_unavailable` if no renderer is connected. */
|
|
53
|
+
request(request: Omit<InteractionRequest, 'id'>, signal: AbortSignal): Promise<InteractionResponse>;
|
|
54
|
+
private pump;
|
|
55
|
+
private finish;
|
|
56
|
+
}
|
|
57
|
+
/** @throws `invalid_arguments` when a question offers no way to answer or has duplicate option IDs. */
|
|
58
|
+
export declare function validateQuestion(question: Question): void;
|
|
59
|
+
/** Validate a human response against the exact request it answers. */
|
|
60
|
+
export declare function validateResponse(request: InteractionRequest, value: unknown): InteractionResponse;
|
|
61
|
+
//# sourceMappingURL=interactions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interactions.d.ts","sourceRoot":"","sources":["../src/interactions.ts"],"names":[],"mappings":"AAEA,iDAAiD;AACjD,MAAM,MAAM,QAAQ,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAEvI,gGAAgG;AAChG,MAAM,MAAM,kBAAkB,GAAG;IAC/B,kDAAkD;IAClD,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,UAAU,GAAG,UAAU,CAAC;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;IAC9B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,0FAA0F;AAC1F,MAAM,MAAM,mBAAmB,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9H,gHAAgH;AAChH,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,EAAE,kBAAkB,EAAE,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAIxG;;;;;;GAMG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,OAAO,CAAC,CAAqB;IACrC,OAAO,CAAC,KAAK,CAAiB;IAC9B,OAAO,CAAC,MAAM,CAAC,CAAU;IACzB,OAAO,CAAC,MAAM,CAAS;IAEvB,2FAA2F;IAC3F,QAAQ,CAAC,OAAO,GAAI,SAAS,kBAAkB,KAAG,CAAC,MAAM,IAAI,CAAC,CAK5D;IAEF,oEAAoE;IACpE,KAAK,IAAI,IAAI;IAEb,OAAO,CAAC,SAAS;IAIjB,0FAA0F;IAC1F,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,kBAAkB,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAcnG,OAAO,CAAC,IAAI;IAcZ,OAAO,CAAC,MAAM;CAWf;AAED,uGAAuG;AACvG,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAGzD;AAED,sEAAsE;AACtE,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,OAAO,GAAG,mBAAmB,CAejG"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
/**
|
|
3
|
+
* Interaction broker: serializes human prompts (FIFO, one at a time) between
|
|
4
|
+
* tool calls and a single connected renderer (TUI, GUI, or your own).
|
|
5
|
+
*
|
|
6
|
+
* Responses are validated against the exact request and are never interpreted
|
|
7
|
+
* as chat turns. Without a connected renderer, requests fail closed.
|
|
8
|
+
*/
|
|
9
|
+
export class ToolInteractions {
|
|
10
|
+
handler;
|
|
11
|
+
queue = [];
|
|
12
|
+
active;
|
|
13
|
+
closed = false;
|
|
14
|
+
/** Attach the renderer. Returns a disconnect function that cancels all pending prompts. */
|
|
15
|
+
connect = (handler) => {
|
|
16
|
+
if (this.closed || this.handler)
|
|
17
|
+
throw new Error('interaction_unavailable');
|
|
18
|
+
this.handler = handler;
|
|
19
|
+
this.pump();
|
|
20
|
+
return () => { this.handler = undefined; this.cancelAll(); };
|
|
21
|
+
};
|
|
22
|
+
/** Permanently close the broker and cancel every pending prompt. */
|
|
23
|
+
close() { this.closed = true; this.handler = undefined; this.cancelAll(); }
|
|
24
|
+
cancelAll() {
|
|
25
|
+
for (const pending of [...this.queue])
|
|
26
|
+
pending.control.abort();
|
|
27
|
+
}
|
|
28
|
+
/** Queue a prompt. Rejects with `interaction_unavailable` if no renderer is connected. */
|
|
29
|
+
request(request, signal) {
|
|
30
|
+
if (this.closed || !this.handler)
|
|
31
|
+
return Promise.reject(new Error('interaction_unavailable'));
|
|
32
|
+
if (signal.aborted)
|
|
33
|
+
return Promise.reject(new Error('tool_cancelled'));
|
|
34
|
+
return new Promise((resolve, reject) => {
|
|
35
|
+
const control = new AbortController();
|
|
36
|
+
const combined = AbortSignal.any([signal, control.signal]);
|
|
37
|
+
const pending = { request: structuredClone({ ...request, id: randomUUID() }), signal: combined, resolve, reject, control, cleanup: () => combined.removeEventListener('abort', abort) };
|
|
38
|
+
const abort = () => { this.finish(pending, undefined, new Error('tool_cancelled')); };
|
|
39
|
+
combined.addEventListener('abort', abort, { once: true });
|
|
40
|
+
this.queue.push(pending);
|
|
41
|
+
this.pump();
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
pump() {
|
|
45
|
+
if (this.active || !this.handler || !this.queue.length)
|
|
46
|
+
return;
|
|
47
|
+
const pending = this.active = this.queue[0];
|
|
48
|
+
const handler = this.handler;
|
|
49
|
+
void Promise.resolve().then(() => {
|
|
50
|
+
pending.signal.throwIfAborted();
|
|
51
|
+
return handler(structuredClone(pending.request), pending.signal);
|
|
52
|
+
}).then(value => {
|
|
53
|
+
if (this.active !== pending)
|
|
54
|
+
return;
|
|
55
|
+
try {
|
|
56
|
+
this.finish(pending, validateResponse(pending.request, value));
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
this.finish(pending, undefined, new Error('invalid_interaction_response'));
|
|
60
|
+
}
|
|
61
|
+
}, () => this.finish(pending, undefined, new Error('interaction_cancelled')));
|
|
62
|
+
}
|
|
63
|
+
finish(pending, value, error) {
|
|
64
|
+
const index = this.queue.indexOf(pending);
|
|
65
|
+
if (index < 0)
|
|
66
|
+
return;
|
|
67
|
+
this.queue.splice(index, 1);
|
|
68
|
+
pending.cleanup();
|
|
69
|
+
if (this.active === pending)
|
|
70
|
+
this.active = undefined;
|
|
71
|
+
// Close the renderer before showing another prompt, including abort races.
|
|
72
|
+
pending.control.abort();
|
|
73
|
+
if (error)
|
|
74
|
+
pending.reject(error);
|
|
75
|
+
else
|
|
76
|
+
pending.resolve(value);
|
|
77
|
+
queueMicrotask(() => this.pump());
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/** @throws `invalid_arguments` when a question offers no way to answer or has duplicate option IDs. */
|
|
81
|
+
export function validateQuestion(question) {
|
|
82
|
+
const options = question.options ?? [];
|
|
83
|
+
if ((!options.length && !question.allowFreeText) || new Set(options.map(o => o.id)).size !== options.length)
|
|
84
|
+
throw new Error('invalid_arguments');
|
|
85
|
+
}
|
|
86
|
+
/** Validate a human response against the exact request it answers. */
|
|
87
|
+
export function validateResponse(request, value) {
|
|
88
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
89
|
+
throw new Error('invalid_response');
|
|
90
|
+
const response = value;
|
|
91
|
+
if (response.id !== request.id)
|
|
92
|
+
throw new Error('stale_response');
|
|
93
|
+
if (response.cancelled === true)
|
|
94
|
+
return { id: request.id, cancelled: true };
|
|
95
|
+
if (request.kind === 'approval') {
|
|
96
|
+
if (typeof response.approved !== 'boolean')
|
|
97
|
+
throw new Error('invalid_response');
|
|
98
|
+
return { id: request.id, approved: response.approved };
|
|
99
|
+
}
|
|
100
|
+
const selected = response.selected ?? [];
|
|
101
|
+
if (!Array.isArray(selected) || new Set(selected).size !== selected.length || selected.some(id => typeof id !== 'string' || !request.options?.some(o => o.id === id)) || (!request.multiSelect && selected.length > 1))
|
|
102
|
+
throw new Error('invalid_response');
|
|
103
|
+
if (response.text !== undefined && (typeof response.text !== 'string' || !request.allowFreeText || response.text.length > 2000))
|
|
104
|
+
throw new Error('invalid_response');
|
|
105
|
+
const text = response.text?.trim();
|
|
106
|
+
if (!selected.length && !text)
|
|
107
|
+
throw new Error('empty_response');
|
|
108
|
+
return { id: request.id, selected, ...(text ? { text } : {}) };
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=interactions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interactions.js","sourceRoot":"","sources":["../src/interactions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AA4BzC;;;;;;GAMG;AACH,MAAM,OAAO,gBAAgB;IACnB,OAAO,CAAsB;IAC7B,KAAK,GAAc,EAAE,CAAC;IACtB,MAAM,CAAW;IACjB,MAAM,GAAG,KAAK,CAAC;IAEvB,2FAA2F;IAClF,OAAO,GAAG,CAAC,OAA2B,EAAgB,EAAE;QAC/D,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC5E,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,IAAI,EAAE,CAAC;QACZ,OAAO,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC;IAC/D,CAAC,CAAC;IAEF,oEAAoE;IACpE,KAAK,KAAW,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;IAEzE,SAAS;QACf,KAAK,MAAM,OAAO,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IACjE,CAAC;IAED,0FAA0F;IAC1F,OAAO,CAAC,OAAuC,EAAE,MAAmB;QAClE,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC,CAAC;QAC9F,IAAI,MAAM,CAAC,OAAO;YAAE,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC;QACvE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,MAAM,OAAO,GAAG,IAAI,eAAe,EAAE,CAAC;YACtC,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;YAC3D,MAAM,OAAO,GAAY,EAAE,OAAO,EAAE,eAAe,CAAC,EAAE,GAAG,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC;YACjM,MAAM,KAAK,GAAG,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,SAAS,EAAE,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACtF,QAAQ,CAAC,gBAAgB,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YAC1D,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACzB,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,IAAI;QACV,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM;YAAE,OAAO;QAC/D,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC;QAC7C,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAC7B,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;YAC/B,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC;YAChC,OAAO,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QACnE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;YACd,IAAI,IAAI,CAAC,MAAM,KAAK,OAAO;gBAAE,OAAO;YACpC,IAAI,CAAC;gBAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,gBAAgB,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;YAAC,CAAC;YACvE,MAAM,CAAC;gBAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,SAAS,EAAE,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC,CAAC;YAAC,CAAC;QACvF,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,SAAS,EAAE,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC;IAChF,CAAC;IAEO,MAAM,CAAC,OAAgB,EAAE,KAA2B,EAAE,KAAa;QACzE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC1C,IAAI,KAAK,GAAG,CAAC;YAAE,OAAO;QACtB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAC5B,OAAO,CAAC,OAAO,EAAE,CAAC;QAClB,IAAI,IAAI,CAAC,MAAM,KAAK,OAAO;YAAE,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;QACrD,2EAA2E;QAC3E,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACxB,IAAI,KAAK;YAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;;YAAM,OAAO,CAAC,OAAO,CAAC,KAAM,CAAC,CAAC;QAC/D,cAAc,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IACpC,CAAC;CACF;AAED,uGAAuG;AACvG,MAAM,UAAU,gBAAgB,CAAC,QAAkB;IACjD,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,IAAI,EAAE,CAAC;IACvC,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;AACpJ,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,gBAAgB,CAAC,OAA2B,EAAE,KAAc;IAC1E,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;IACrG,MAAM,QAAQ,GAAG,KAA4B,CAAC;IAC9C,IAAI,QAAQ,CAAC,EAAE,KAAK,OAAO,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;IAClE,IAAI,QAAQ,CAAC,SAAS,KAAK,IAAI;QAAE,OAAO,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IAC5E,IAAI,OAAO,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QAChC,IAAI,OAAO,QAAQ,CAAC,QAAQ,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;QAChF,OAAO,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC;IACzD,CAAC;IACD,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,IAAI,EAAE,CAAC;IACzC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,WAAW,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;IAC5P,IAAI,QAAQ,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,OAAO,QAAQ,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,aAAa,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;IACrK,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;IACnC,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;IACjE,OAAO,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,QAAQ,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;AACjE,CAAC"}
|
package/dist/memory.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The only shell command the agent may run: commit Markdown changes in its own
|
|
3
|
+
* MemFS repository, with hooks disabled and a fixed author.
|
|
4
|
+
*/
|
|
5
|
+
export declare function memoryCommitCommand(root: string, author?: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* Strict per-call permission for harness memory tools: own Markdown files only;
|
|
8
|
+
* no general shell, traversal, dot-files (including `.git`), symlinks or hard links.
|
|
9
|
+
*/
|
|
10
|
+
export declare function allowMemoryTool(name: string, input: Record<string, unknown>, root?: string, author?: string): boolean;
|
|
11
|
+
//# sourceMappingURL=memory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"AAMA;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,SAAuB,GAAG,MAAM,CAGvF;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAsBrH"}
|
package/dist/memory.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { lstatSync, realpathSync } from 'node:fs';
|
|
2
|
+
import { isAbsolute, relative, resolve, sep } from 'node:path';
|
|
3
|
+
import { INTERNAL_MEMORY_TOOLS } from './definition.js';
|
|
4
|
+
const quote = (value) => `'${value.replaceAll("'", "'\\''")}'`;
|
|
5
|
+
/**
|
|
6
|
+
* The only shell command the agent may run: commit Markdown changes in its own
|
|
7
|
+
* MemFS repository, with hooks disabled and a fixed author.
|
|
8
|
+
*/
|
|
9
|
+
export function memoryCommitCommand(root, author = 'ai-sdk-letta agent') {
|
|
10
|
+
const git = `git -c core.hooksPath=/dev/null -C ${quote(root)}`;
|
|
11
|
+
return `${git} add -- '*.md' && ${git} -c user.name=${quote(author.replace(/[\r\n]/g, ' '))} -c user.email='agent@localhost' commit -m 'Update agent memory'`;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Strict per-call permission for harness memory tools: own Markdown files only;
|
|
15
|
+
* no general shell, traversal, dot-files (including `.git`), symlinks or hard links.
|
|
16
|
+
*/
|
|
17
|
+
export function allowMemoryTool(name, input, root, author) {
|
|
18
|
+
if (!root || !INTERNAL_MEMORY_TOOLS.includes(name))
|
|
19
|
+
return false;
|
|
20
|
+
if (name === 'Bash')
|
|
21
|
+
return input.command === memoryCommitCommand(root, author) && !input.run_in_background;
|
|
22
|
+
if (typeof input.file_path !== 'string' || !isAbsolute(input.file_path) || !input.file_path.endsWith('.md'))
|
|
23
|
+
return false;
|
|
24
|
+
try {
|
|
25
|
+
const canonicalRoot = realpathSync(root);
|
|
26
|
+
const path = resolve(input.file_path);
|
|
27
|
+
// Accept the backend-provided spelling (e.g. macOS /var -> /private/var)
|
|
28
|
+
// or its canonical spelling; inspect every component below the real root.
|
|
29
|
+
const rawSuffix = relative(resolve(root), path);
|
|
30
|
+
const suffix = !rawSuffix.startsWith(`..${sep}`) && rawSuffix !== '..' && !isAbsolute(rawSuffix) ? rawSuffix : relative(canonicalRoot, path);
|
|
31
|
+
if (!suffix || suffix.startsWith(`..${sep}`) || suffix === '..' || isAbsolute(suffix))
|
|
32
|
+
return false;
|
|
33
|
+
const parts = suffix.split(sep);
|
|
34
|
+
if (parts.some(part => part.startsWith('.')))
|
|
35
|
+
return false;
|
|
36
|
+
let current = canonicalRoot;
|
|
37
|
+
for (const part of parts) {
|
|
38
|
+
current = resolve(current, part);
|
|
39
|
+
try {
|
|
40
|
+
const stat = lstatSync(current);
|
|
41
|
+
if (stat.isSymbolicLink() || (stat.isFile() && stat.nlink > 1))
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
if (error.code !== 'ENOENT')
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { ListMessagesOptions, ListMessagesResult, LettaConversation } from '@letta-ai/letta-agent-sdk';
|
|
2
|
+
/** One row of a conversation picker. */
|
|
3
|
+
export type ConversationEntry = {
|
|
4
|
+
id: string;
|
|
5
|
+
title: string;
|
|
6
|
+
date: string;
|
|
7
|
+
};
|
|
8
|
+
/** Read-only access to the current agent's conversations, used by pickers and search. */
|
|
9
|
+
export type NavigationSource = {
|
|
10
|
+
agentId: string;
|
|
11
|
+
currentId: string;
|
|
12
|
+
list: (signal?: AbortSignal) => Promise<{
|
|
13
|
+
entries: ConversationEntry[];
|
|
14
|
+
limited: boolean;
|
|
15
|
+
}>;
|
|
16
|
+
page: (id: string, options: ListMessagesOptions) => Promise<ListMessagesResult>;
|
|
17
|
+
validate: (id: string, signal?: AbortSignal) => Promise<void>;
|
|
18
|
+
};
|
|
19
|
+
/** Newest conversations of one agent (up to 200 plus `default`), excluding archived ones. */
|
|
20
|
+
export declare function listNavigationEntries(list: (query: {
|
|
21
|
+
agentId: string;
|
|
22
|
+
limit: number;
|
|
23
|
+
order: 'desc';
|
|
24
|
+
orderBy: 'createdAt';
|
|
25
|
+
after?: string;
|
|
26
|
+
}) => Promise<LettaConversation[]>, agentId: string, signal?: AbortSignal): Promise<{
|
|
27
|
+
entries: ConversationEntry[];
|
|
28
|
+
limited: boolean;
|
|
29
|
+
}>;
|
|
30
|
+
export declare const SEARCH_CONVERSATIONS = 50;
|
|
31
|
+
export declare const SEARCH_RECORDS = 500;
|
|
32
|
+
export declare const SEARCH_TOTAL = 5000;
|
|
33
|
+
export declare const SEARCH_MATCHES = 100;
|
|
34
|
+
export declare const SEARCH_MILLISECONDS = 30000;
|
|
35
|
+
/** A short excerpt of `text` around the first match of `query`. */
|
|
36
|
+
export declare function snippet(text: string, query: string): string;
|
|
37
|
+
export type SearchMatch = {
|
|
38
|
+
conversation: ConversationEntry;
|
|
39
|
+
role: string;
|
|
40
|
+
snippet: string;
|
|
41
|
+
};
|
|
42
|
+
/** Literal, case-insensitive text search. Only authoritative human/assistant text
|
|
43
|
+
* enters the projection: never tools, reasoning, system or memory records. */
|
|
44
|
+
export declare function searchConversations(source: NavigationSource, entries: ConversationEntry[], query: string, signal: AbortSignal, progress?: (text: string) => void): Promise<{
|
|
45
|
+
matches: SearchMatch[];
|
|
46
|
+
records: number;
|
|
47
|
+
scanned: number;
|
|
48
|
+
limited: boolean;
|
|
49
|
+
}>;
|
|
50
|
+
//# sourceMappingURL=navigation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navigation.d.ts","sourceRoot":"","sources":["../src/navigation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAG5G,wCAAwC;AACxC,MAAM,MAAM,iBAAiB,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAC5E,yFAAyF;AACzF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC;QAAE,OAAO,EAAE,iBAAiB,EAAE,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAC5F,IAAI,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,KAAK,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAChF,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/D,CAAC;AACF,6FAA6F;AAC7F,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,WAAW,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,KAAK,OAAO,CAAC,iBAAiB,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW;;;GAqBxN;AAED,eAAO,MAAM,oBAAoB,KAAK,CAAC;AACvC,eAAO,MAAM,cAAc,MAAM,CAAC;AAClC,eAAO,MAAM,YAAY,OAAO,CAAC;AACjC,eAAO,MAAM,cAAc,MAAM,CAAC;AAClC,eAAO,MAAM,mBAAmB,QAAS,CAAC;AAE1C,mEAAmE;AACnE,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,UAKlD;AACD,MAAM,MAAM,WAAW,GAAG;IAAE,YAAY,EAAE,iBAAiB,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAC7F;8EAC8E;AAC9E,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,gBAAgB,EAAE,OAAO,EAAE,iBAAiB,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAe;;;;;GA8BhL"}
|