@band-ai/sdk 0.1.6 → 0.1.10
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 +372 -0
- package/dist/{ClaudeSDKAdapter-CRq4R-WB.d.cts → ClaudeSDKAdapter-DfjaI5ke.d.cts} +9 -7
- package/dist/{ClaudeSDKAdapter-BHOkjN3X.d.ts → ClaudeSDKAdapter-DonPGJ43.d.ts} +9 -7
- package/dist/{acp-server-BdRz9_UN.d.cts → acp-server-CUBXIiG6.d.cts} +2 -2
- package/dist/{acp-server-B1Da7L6u.d.ts → acp-server-NZAeg-WO.d.ts} +2 -2
- package/dist/adapters.cjs +494 -106
- package/dist/adapters.d.cts +12 -12
- package/dist/adapters.d.ts +12 -12
- package/dist/adapters.js +7 -7
- package/dist/{backends-SVMT-7l4.d.cts → backends-DYtEhCZG.d.cts} +7 -2
- package/dist/{backends-CzDbiQar.d.ts → backends-oYAb7EU-.d.ts} +7 -2
- package/dist/{chunk-MSL6CWHY.js → chunk-2BHHR6YW.js} +17 -16
- package/dist/{chunk-EDPKUUJL.js → chunk-6RXWL6TC.js} +9 -1
- package/dist/{chunk-SFVKOEQH.js → chunk-DNPVCR3S.js} +92 -14
- package/dist/{chunk-I5EZG52P.js → chunk-FP237EAG.js} +424 -136
- package/dist/{chunk-RHVH2GZR.js → chunk-J3M3PFFY.js} +81 -31
- package/dist/{chunk-GVEQ3RAH.js → chunk-MLROFDKR.js} +132 -23
- package/dist/{chunk-INA6YZTZ.js → chunk-RDM4TE4B.js} +32 -30
- package/dist/chunk-US226AS4.js +130 -0
- package/dist/{chunk-W5NDZSYE.js → chunk-XA4N2JPH.js} +1 -1
- package/dist/converters.cjs +469 -13
- package/dist/converters.d.cts +5 -5
- package/dist/converters.d.ts +5 -5
- package/dist/converters.js +3 -2
- package/dist/core.cjs +45 -2
- package/dist/core.d.cts +4 -3
- package/dist/core.d.ts +4 -3
- package/dist/core.js +5 -1
- package/dist/disconnectReason-IuADl6TH.d.cts +34 -0
- package/dist/disconnectReason-IuADl6TH.d.ts +34 -0
- package/dist/{dtos-DUpbIu8k.d.cts → dtos-Dd_fTfLn.d.cts} +26 -6
- package/dist/{dtos-DUpbIu8k.d.ts → dtos-Dd_fTfLn.d.ts} +26 -6
- package/dist/index.cjs +1089 -269
- package/dist/index.d.cts +16 -15
- package/dist/index.d.ts +16 -15
- package/dist/index.js +14 -8
- package/dist/linear.cjs +985 -53
- package/dist/linear.d.cts +137 -7
- package/dist/linear.d.ts +137 -7
- package/dist/linear.js +974 -53
- package/dist/mcp-claude.cjs +303 -32
- package/dist/mcp-claude.d.cts +3 -3
- package/dist/mcp-claude.d.ts +3 -3
- package/dist/mcp-claude.js +210 -12
- package/dist/mcp.cjs +313 -45
- package/dist/mcp.d.cts +5 -5
- package/dist/mcp.d.ts +5 -5
- package/dist/mcp.js +3 -3
- package/dist/{opencode-BBcDchcN.d.cts → opencode--iA5-KYk.d.cts} +2 -2
- package/dist/{opencode-DthQQUsZ.d.ts → opencode-YNacv-eJ.d.ts} +2 -2
- package/dist/{pagination-CcDkVFxK.d.ts → pagination-BBLsYLhT.d.ts} +2 -2
- package/dist/{pagination-BPiys10t.d.cts → pagination-CqidD-L_.d.cts} +2 -2
- package/dist/{protocols-DrhzOH6K.d.ts → protocols-BF6jamIl.d.ts} +1 -1
- package/dist/{protocols-CInhtFpA.d.cts → protocols-D2bTrQ_t.d.cts} +1 -1
- package/dist/rest.d.cts +5 -5
- package/dist/rest.d.ts +5 -5
- package/dist/runtime.cjs +721 -172
- package/dist/runtime.d.cts +15 -10
- package/dist/runtime.d.ts +15 -10
- package/dist/runtime.js +11 -8
- package/dist/{schemas-vos1AaBc.d.ts → schemas-B1Fd3oUM.d.ts} +17 -8
- package/dist/{schemas-BpEBkq5V.d.cts → schemas-CI0qgcp_.d.cts} +17 -8
- package/dist/{sdk-CcnQ5OUC.d.ts → sdk-CyqN1W5g.d.ts} +32 -2
- package/dist/{sdk-CwTAxhwI.d.cts → sdk-D2rTDU_o.d.cts} +32 -2
- package/dist/{simpleAdapter-DqhvjsGr.d.cts → simpleAdapter-C_f-01Cu.d.cts} +1 -1
- package/dist/{simpleAdapter-9OE_p6QW.d.ts → simpleAdapter-qQt-tSz4.d.ts} +1 -1
- package/dist/testing.d.cts +3 -3
- package/dist/testing.d.ts +3 -3
- package/dist/{types-CovcHpYf.d.cts → types-CKqrhGB1.d.cts} +2 -2
- package/dist/{types-CxII3XkA.d.ts → types-D3AsUnd0.d.ts} +1 -1
- package/dist/{types-7jVzOeOP.d.ts → types-DNySTI_8.d.ts} +2 -2
- package/dist/{types-CSHFipIc.d.cts → types-DtMms5Fi.d.cts} +1 -1
- package/package.json +22 -21
package/dist/runtime.cjs
CHANGED
|
@@ -38,6 +38,7 @@ __export(runtime_exports, {
|
|
|
38
38
|
HUB_ROOM_SYSTEM_PROMPT: () => HUB_ROOM_SYSTEM_PROMPT,
|
|
39
39
|
HistoryProvider: () => HistoryProvider,
|
|
40
40
|
MCP_TOOL_PREFIX: () => MCP_TOOL_PREFIX,
|
|
41
|
+
MEMORY_SECTION: () => MEMORY_SECTION,
|
|
41
42
|
MEMORY_TOOL_NAMES: () => MEMORY_TOOL_NAMES,
|
|
42
43
|
MessageRetryTracker: () => MessageRetryTracker,
|
|
43
44
|
ParticipantTracker: () => ParticipantTracker,
|
|
@@ -1172,6 +1173,108 @@ var DEFAULT_AGENT_TOOLS_CAPABILITIES = {
|
|
|
1172
1173
|
memory: true
|
|
1173
1174
|
};
|
|
1174
1175
|
|
|
1176
|
+
// src/contracts/memory.ts
|
|
1177
|
+
var SENSORY_MEMORY_TYPES = [
|
|
1178
|
+
"iconic",
|
|
1179
|
+
// Visual input
|
|
1180
|
+
"echoic",
|
|
1181
|
+
// Auditory input
|
|
1182
|
+
"haptic"
|
|
1183
|
+
// Tactile input
|
|
1184
|
+
];
|
|
1185
|
+
var COGNITIVE_MEMORY_TYPES = [
|
|
1186
|
+
"episodic",
|
|
1187
|
+
// Events that occurred
|
|
1188
|
+
"semantic",
|
|
1189
|
+
// Facts, preferences, learned knowledge
|
|
1190
|
+
"procedural"
|
|
1191
|
+
// How to perform tasks
|
|
1192
|
+
];
|
|
1193
|
+
function namedValues(values) {
|
|
1194
|
+
return Object.fromEntries(values.map((value) => [value, value]));
|
|
1195
|
+
}
|
|
1196
|
+
var MEMORY_SYSTEM_TYPES = {
|
|
1197
|
+
sensory: SENSORY_MEMORY_TYPES,
|
|
1198
|
+
// Brief sensory inputs
|
|
1199
|
+
working: COGNITIVE_MEMORY_TYPES,
|
|
1200
|
+
// Short-term session context
|
|
1201
|
+
long_term: COGNITIVE_MEMORY_TYPES
|
|
1202
|
+
// Persistent cross-conversation memory
|
|
1203
|
+
};
|
|
1204
|
+
var MEMORY_SYSTEMS = Object.keys(MEMORY_SYSTEM_TYPES);
|
|
1205
|
+
var MEMORY_TYPES = [
|
|
1206
|
+
...SENSORY_MEMORY_TYPES,
|
|
1207
|
+
...COGNITIVE_MEMORY_TYPES
|
|
1208
|
+
];
|
|
1209
|
+
var MEMORY_SEGMENTS = [
|
|
1210
|
+
"user",
|
|
1211
|
+
// User preferences or profile info
|
|
1212
|
+
"agent",
|
|
1213
|
+
// Facts or events about agents/entities
|
|
1214
|
+
"tool",
|
|
1215
|
+
// Tool usage or task procedures
|
|
1216
|
+
"guideline"
|
|
1217
|
+
// Behavioral rules or policies
|
|
1218
|
+
];
|
|
1219
|
+
var MEMORY_STORE_SCOPES = [
|
|
1220
|
+
"subject",
|
|
1221
|
+
// About one person/agent; requires subject_id
|
|
1222
|
+
"organization"
|
|
1223
|
+
// Shared org-wide
|
|
1224
|
+
];
|
|
1225
|
+
var MEMORY_LIST_SCOPES = [
|
|
1226
|
+
"subject",
|
|
1227
|
+
// Subject-scoped memories only
|
|
1228
|
+
"organization",
|
|
1229
|
+
// Organization-scoped memories only
|
|
1230
|
+
"all"
|
|
1231
|
+
// Both scopes (no scope filter)
|
|
1232
|
+
];
|
|
1233
|
+
var MEMORY_STATUSES = [
|
|
1234
|
+
"active",
|
|
1235
|
+
// Normal, visible memories
|
|
1236
|
+
"superseded",
|
|
1237
|
+
// Outdated; soft-deleted via thenvoi_supersede_memory
|
|
1238
|
+
"archived",
|
|
1239
|
+
// Hidden but preserved via thenvoi_archive_memory
|
|
1240
|
+
"all"
|
|
1241
|
+
// Any status (no filter)
|
|
1242
|
+
];
|
|
1243
|
+
var MEMORY_SYSTEM = namedValues(MEMORY_SYSTEMS);
|
|
1244
|
+
var MEMORY_TYPE = namedValues(MEMORY_TYPES);
|
|
1245
|
+
var MEMORY_SEGMENT = namedValues(MEMORY_SEGMENTS);
|
|
1246
|
+
var MEMORY_STORE_SCOPE = namedValues(MEMORY_STORE_SCOPES);
|
|
1247
|
+
function isMemorySystem(value) {
|
|
1248
|
+
return MEMORY_SYSTEMS.includes(value);
|
|
1249
|
+
}
|
|
1250
|
+
function isMemoryType(value) {
|
|
1251
|
+
return MEMORY_TYPES.includes(value);
|
|
1252
|
+
}
|
|
1253
|
+
function isMemoryTypeForSystem(system, type) {
|
|
1254
|
+
return MEMORY_SYSTEM_TYPES[system].includes(type);
|
|
1255
|
+
}
|
|
1256
|
+
function isMemorySegment(value) {
|
|
1257
|
+
return MEMORY_SEGMENTS.includes(value);
|
|
1258
|
+
}
|
|
1259
|
+
function isMemoryStoreScope(value) {
|
|
1260
|
+
return MEMORY_STORE_SCOPES.includes(value);
|
|
1261
|
+
}
|
|
1262
|
+
function isMemoryListScope(value) {
|
|
1263
|
+
return MEMORY_LIST_SCOPES.includes(value);
|
|
1264
|
+
}
|
|
1265
|
+
function isMemoryStatus(value) {
|
|
1266
|
+
return MEMORY_STATUSES.includes(value);
|
|
1267
|
+
}
|
|
1268
|
+
function expectedList(values) {
|
|
1269
|
+
return values.join(", ");
|
|
1270
|
+
}
|
|
1271
|
+
function expectedMemoryTypesForSystem(system) {
|
|
1272
|
+
return expectedList(MEMORY_SYSTEM_TYPES[system]);
|
|
1273
|
+
}
|
|
1274
|
+
function memoryTypeForSystemError(system) {
|
|
1275
|
+
return `type must be one of: ${expectedMemoryTypesForSystem(system)} for system "${system}"`;
|
|
1276
|
+
}
|
|
1277
|
+
|
|
1175
1278
|
// src/runtime/tools/schemas.ts
|
|
1176
1279
|
var TOOL_MODELS = {
|
|
1177
1280
|
thenvoi_send_message: {
|
|
@@ -1359,29 +1462,22 @@ var TOOL_MODELS = {
|
|
|
1359
1462
|
},
|
|
1360
1463
|
scope: {
|
|
1361
1464
|
type: "string",
|
|
1362
|
-
enum: [
|
|
1465
|
+
enum: [...MEMORY_LIST_SCOPES],
|
|
1363
1466
|
description: "Filter by scope."
|
|
1364
1467
|
},
|
|
1365
1468
|
system: {
|
|
1366
1469
|
type: "string",
|
|
1367
|
-
enum: [
|
|
1470
|
+
enum: [...MEMORY_SYSTEMS],
|
|
1368
1471
|
description: "Filter by memory system."
|
|
1369
1472
|
},
|
|
1370
1473
|
type: {
|
|
1371
1474
|
type: "string",
|
|
1372
|
-
enum: [
|
|
1373
|
-
"iconic",
|
|
1374
|
-
"echoic",
|
|
1375
|
-
"haptic",
|
|
1376
|
-
"episodic",
|
|
1377
|
-
"semantic",
|
|
1378
|
-
"procedural"
|
|
1379
|
-
],
|
|
1475
|
+
enum: [...MEMORY_TYPES],
|
|
1380
1476
|
description: "Filter by memory type."
|
|
1381
1477
|
},
|
|
1382
1478
|
segment: {
|
|
1383
1479
|
type: "string",
|
|
1384
|
-
enum: [
|
|
1480
|
+
enum: [...MEMORY_SEGMENTS],
|
|
1385
1481
|
description: "Filter by segment."
|
|
1386
1482
|
},
|
|
1387
1483
|
content_query: {
|
|
@@ -1396,7 +1492,7 @@ var TOOL_MODELS = {
|
|
|
1396
1492
|
},
|
|
1397
1493
|
status: {
|
|
1398
1494
|
type: "string",
|
|
1399
|
-
enum: [
|
|
1495
|
+
enum: [...MEMORY_STATUSES],
|
|
1400
1496
|
description: "Filter by status."
|
|
1401
1497
|
}
|
|
1402
1498
|
},
|
|
@@ -1411,24 +1507,17 @@ var TOOL_MODELS = {
|
|
|
1411
1507
|
},
|
|
1412
1508
|
system: {
|
|
1413
1509
|
type: "string",
|
|
1414
|
-
enum: [
|
|
1510
|
+
enum: [...MEMORY_SYSTEMS],
|
|
1415
1511
|
description: "Memory system tier."
|
|
1416
1512
|
},
|
|
1417
1513
|
type: {
|
|
1418
1514
|
type: "string",
|
|
1419
|
-
enum: [
|
|
1420
|
-
"iconic",
|
|
1421
|
-
"echoic",
|
|
1422
|
-
"haptic",
|
|
1423
|
-
"episodic",
|
|
1424
|
-
"semantic",
|
|
1425
|
-
"procedural"
|
|
1426
|
-
],
|
|
1515
|
+
enum: [...MEMORY_TYPES],
|
|
1427
1516
|
description: "Memory type (must be valid for selected system)."
|
|
1428
1517
|
},
|
|
1429
1518
|
segment: {
|
|
1430
1519
|
type: "string",
|
|
1431
|
-
enum: [
|
|
1520
|
+
enum: [...MEMORY_SEGMENTS],
|
|
1432
1521
|
description: "Logical segment."
|
|
1433
1522
|
},
|
|
1434
1523
|
thought: {
|
|
@@ -1437,7 +1526,7 @@ var TOOL_MODELS = {
|
|
|
1437
1526
|
},
|
|
1438
1527
|
scope: {
|
|
1439
1528
|
type: "string",
|
|
1440
|
-
enum: [
|
|
1529
|
+
enum: [...MEMORY_STORE_SCOPES],
|
|
1441
1530
|
description: "Visibility scope."
|
|
1442
1531
|
},
|
|
1443
1532
|
subject_id: {
|
|
@@ -1547,40 +1636,6 @@ var CONTACT_REQUEST_ACTIONS = /* @__PURE__ */ new Set([
|
|
|
1547
1636
|
"reject",
|
|
1548
1637
|
"cancel"
|
|
1549
1638
|
]);
|
|
1550
|
-
var MEMORY_SYSTEMS = /* @__PURE__ */ new Set([
|
|
1551
|
-
"sensory",
|
|
1552
|
-
"working",
|
|
1553
|
-
"long_term"
|
|
1554
|
-
]);
|
|
1555
|
-
var MEMORY_TYPES = /* @__PURE__ */ new Set([
|
|
1556
|
-
"iconic",
|
|
1557
|
-
"echoic",
|
|
1558
|
-
"haptic",
|
|
1559
|
-
"episodic",
|
|
1560
|
-
"semantic",
|
|
1561
|
-
"procedural"
|
|
1562
|
-
]);
|
|
1563
|
-
var MEMORY_SEGMENTS = /* @__PURE__ */ new Set([
|
|
1564
|
-
"user",
|
|
1565
|
-
"agent",
|
|
1566
|
-
"tool",
|
|
1567
|
-
"guideline"
|
|
1568
|
-
]);
|
|
1569
|
-
var LIST_MEMORY_SCOPES = /* @__PURE__ */ new Set([
|
|
1570
|
-
"subject",
|
|
1571
|
-
"organization",
|
|
1572
|
-
"all"
|
|
1573
|
-
]);
|
|
1574
|
-
var LIST_MEMORY_STATUSES = /* @__PURE__ */ new Set([
|
|
1575
|
-
"active",
|
|
1576
|
-
"superseded",
|
|
1577
|
-
"archived",
|
|
1578
|
-
"all"
|
|
1579
|
-
]);
|
|
1580
|
-
var MEMORY_SCOPES = /* @__PURE__ */ new Set([
|
|
1581
|
-
"subject",
|
|
1582
|
-
"organization"
|
|
1583
|
-
]);
|
|
1584
1639
|
var AgentTools = class {
|
|
1585
1640
|
roomId;
|
|
1586
1641
|
capabilities;
|
|
@@ -2158,6 +2213,9 @@ var AgentTools = class {
|
|
|
2158
2213
|
const status = this.normalizeOptionalMemoryStatus(arguments_.status);
|
|
2159
2214
|
const subjectId = this.normalizeOptionalString(arguments_.subject_id);
|
|
2160
2215
|
const contentQuery = this.normalizeOptionalString(arguments_.content_query);
|
|
2216
|
+
if (system && type && !isMemoryTypeForSystem(system, type)) {
|
|
2217
|
+
throw new ValidationError(memoryTypeForSystemError(system));
|
|
2218
|
+
}
|
|
2161
2219
|
return {
|
|
2162
2220
|
...subjectId ? { subject_id: subjectId } : {},
|
|
2163
2221
|
...scope ? { scope } : {},
|
|
@@ -2179,13 +2237,21 @@ var AgentTools = class {
|
|
|
2179
2237
|
const subjectId = this.normalizeOptionalString(arguments_.subject_id);
|
|
2180
2238
|
const metadata = this.normalizeOptionalMetadata(arguments_.metadata);
|
|
2181
2239
|
if (!system) {
|
|
2182
|
-
throw new ValidationError(
|
|
2240
|
+
throw new ValidationError(`system must be one of: ${expectedList(MEMORY_SYSTEMS)}`);
|
|
2183
2241
|
}
|
|
2184
2242
|
if (!type) {
|
|
2185
|
-
throw new ValidationError(
|
|
2243
|
+
throw new ValidationError(`type must be one of: ${expectedList(MEMORY_TYPES)}`);
|
|
2244
|
+
}
|
|
2245
|
+
if (!isMemoryTypeForSystem(system, type)) {
|
|
2246
|
+
throw new ValidationError(memoryTypeForSystemError(system));
|
|
2186
2247
|
}
|
|
2187
2248
|
if (!segment) {
|
|
2188
|
-
throw new ValidationError(
|
|
2249
|
+
throw new ValidationError(`segment must be one of: ${expectedList(MEMORY_SEGMENTS)}`);
|
|
2250
|
+
}
|
|
2251
|
+
if (scope === "subject" && !subjectId) {
|
|
2252
|
+
throw new ValidationError(
|
|
2253
|
+
'scope="subject" requires a subject_id (the UUID of the person or agent the memory is about). If you do not have a concrete subject UUID, retry with scope="organization" and omit subject_id. Do not invent a UUID.'
|
|
2254
|
+
);
|
|
2189
2255
|
}
|
|
2190
2256
|
return {
|
|
2191
2257
|
content,
|
|
@@ -2265,8 +2331,8 @@ var AgentTools = class {
|
|
|
2265
2331
|
if (!normalized) {
|
|
2266
2332
|
return void 0;
|
|
2267
2333
|
}
|
|
2268
|
-
if (!
|
|
2269
|
-
throw new ValidationError(
|
|
2334
|
+
if (!isMemoryListScope(normalized)) {
|
|
2335
|
+
throw new ValidationError(`scope must be one of: ${expectedList(MEMORY_LIST_SCOPES)}`);
|
|
2270
2336
|
}
|
|
2271
2337
|
return normalized;
|
|
2272
2338
|
}
|
|
@@ -2276,7 +2342,7 @@ var AgentTools = class {
|
|
|
2276
2342
|
return void 0;
|
|
2277
2343
|
}
|
|
2278
2344
|
if (!isMemorySystem(normalized)) {
|
|
2279
|
-
throw new ValidationError(
|
|
2345
|
+
throw new ValidationError(`system must be one of: ${expectedList(MEMORY_SYSTEMS)}`);
|
|
2280
2346
|
}
|
|
2281
2347
|
return normalized;
|
|
2282
2348
|
}
|
|
@@ -2286,7 +2352,7 @@ var AgentTools = class {
|
|
|
2286
2352
|
return void 0;
|
|
2287
2353
|
}
|
|
2288
2354
|
if (!isMemoryType(normalized)) {
|
|
2289
|
-
throw new ValidationError(
|
|
2355
|
+
throw new ValidationError(`type must be one of: ${expectedList(MEMORY_TYPES)}`);
|
|
2290
2356
|
}
|
|
2291
2357
|
return normalized;
|
|
2292
2358
|
}
|
|
@@ -2296,7 +2362,7 @@ var AgentTools = class {
|
|
|
2296
2362
|
return void 0;
|
|
2297
2363
|
}
|
|
2298
2364
|
if (!isMemorySegment(normalized)) {
|
|
2299
|
-
throw new ValidationError(
|
|
2365
|
+
throw new ValidationError(`segment must be one of: ${expectedList(MEMORY_SEGMENTS)}`);
|
|
2300
2366
|
}
|
|
2301
2367
|
return normalized;
|
|
2302
2368
|
}
|
|
@@ -2306,7 +2372,7 @@ var AgentTools = class {
|
|
|
2306
2372
|
return void 0;
|
|
2307
2373
|
}
|
|
2308
2374
|
if (!isMemoryStatus(normalized)) {
|
|
2309
|
-
throw new ValidationError(
|
|
2375
|
+
throw new ValidationError(`status must be one of: ${expectedList(MEMORY_STATUSES)}`);
|
|
2310
2376
|
}
|
|
2311
2377
|
return normalized;
|
|
2312
2378
|
}
|
|
@@ -2315,8 +2381,8 @@ var AgentTools = class {
|
|
|
2315
2381
|
if (!normalized) {
|
|
2316
2382
|
return void 0;
|
|
2317
2383
|
}
|
|
2318
|
-
if (!
|
|
2319
|
-
throw new ValidationError(
|
|
2384
|
+
if (!isMemoryStoreScope(normalized)) {
|
|
2385
|
+
throw new ValidationError(`scope must be one of: ${expectedList(MEMORY_STORE_SCOPES)}`);
|
|
2320
2386
|
}
|
|
2321
2387
|
return normalized;
|
|
2322
2388
|
}
|
|
@@ -2324,24 +2390,6 @@ var AgentTools = class {
|
|
|
2324
2390
|
function isContactRequestAction(value) {
|
|
2325
2391
|
return CONTACT_REQUEST_ACTIONS.has(value);
|
|
2326
2392
|
}
|
|
2327
|
-
function isMemorySystem(value) {
|
|
2328
|
-
return MEMORY_SYSTEMS.has(value);
|
|
2329
|
-
}
|
|
2330
|
-
function isMemoryType(value) {
|
|
2331
|
-
return MEMORY_TYPES.has(value);
|
|
2332
|
-
}
|
|
2333
|
-
function isMemorySegment(value) {
|
|
2334
|
-
return MEMORY_SEGMENTS.has(value);
|
|
2335
|
-
}
|
|
2336
|
-
function isStoreMemoryScope(value) {
|
|
2337
|
-
return MEMORY_SCOPES.has(value);
|
|
2338
|
-
}
|
|
2339
|
-
function isListMemoryScope(value) {
|
|
2340
|
-
return LIST_MEMORY_SCOPES.has(value);
|
|
2341
|
-
}
|
|
2342
|
-
function isMemoryStatus(value) {
|
|
2343
|
-
return LIST_MEMORY_STATUSES.has(value);
|
|
2344
|
-
}
|
|
2345
2393
|
function coercePositiveInt(value, fallback) {
|
|
2346
2394
|
const num = Number(value ?? fallback);
|
|
2347
2395
|
return Number.isFinite(num) && num >= 1 ? Math.floor(num) : fallback;
|
|
@@ -2381,17 +2429,19 @@ function validateToolArgs(toolName, args) {
|
|
|
2381
2429
|
}
|
|
2382
2430
|
}
|
|
2383
2431
|
if (toolName === "thenvoi_store_memory") {
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
const validSegments = ["user", "agent", "tool", "guideline"];
|
|
2387
|
-
if (typeof args.system === "string" && !validSystems.includes(args.system)) {
|
|
2388
|
-
errors.push(`system: Invalid value '${args.system}'. Expected one of: ${validSystems.join(", ")}`);
|
|
2432
|
+
if (typeof args.system === "string" && !isMemorySystem(args.system)) {
|
|
2433
|
+
errors.push(`system: Invalid value '${args.system}'. Expected one of: ${expectedList(MEMORY_SYSTEMS)}`);
|
|
2389
2434
|
}
|
|
2390
|
-
if (typeof args.type === "string" && !
|
|
2391
|
-
errors.push(`type: Invalid value '${args.type}'. Expected one of: ${
|
|
2435
|
+
if (typeof args.type === "string" && !isMemoryType(args.type)) {
|
|
2436
|
+
errors.push(`type: Invalid value '${args.type}'. Expected one of: ${expectedList(MEMORY_TYPES)}`);
|
|
2392
2437
|
}
|
|
2393
|
-
if (typeof args.
|
|
2394
|
-
errors.push(
|
|
2438
|
+
if (typeof args.system === "string" && isMemorySystem(args.system) && typeof args.type === "string" && isMemoryType(args.type) && !isMemoryTypeForSystem(args.system, args.type)) {
|
|
2439
|
+
errors.push(
|
|
2440
|
+
`type: Invalid value '${args.type}' for system '${args.system}'. Expected one of: ${expectedMemoryTypesForSystem(args.system)}`
|
|
2441
|
+
);
|
|
2442
|
+
}
|
|
2443
|
+
if (typeof args.segment === "string" && !isMemorySegment(args.segment)) {
|
|
2444
|
+
errors.push(`segment: Invalid value '${args.segment}'. Expected one of: ${expectedList(MEMORY_SEGMENTS)}`);
|
|
2395
2445
|
}
|
|
2396
2446
|
}
|
|
2397
2447
|
if (errors.length > 0) {
|
|
@@ -2471,7 +2521,7 @@ function replaceUuidMentions(content, participants) {
|
|
|
2471
2521
|
const participantId = participant.id;
|
|
2472
2522
|
const handle = participant.handle;
|
|
2473
2523
|
if (typeof participantId === "string" && typeof handle === "string") {
|
|
2474
|
-
next = next.replaceAll(`@[[${participantId}]]`,
|
|
2524
|
+
next = next.replaceAll(`@[[${participantId}]]`, ensureHandlePrefix(handle) ?? "");
|
|
2475
2525
|
}
|
|
2476
2526
|
}
|
|
2477
2527
|
return next;
|
|
@@ -2503,7 +2553,9 @@ function buildParticipantsMessage(participants) {
|
|
|
2503
2553
|
const participantType = String(participant.type ?? "Unknown");
|
|
2504
2554
|
const participantName = String(participant.name ?? "Unknown");
|
|
2505
2555
|
const participantHandle = String(participant.handle ?? "Unknown");
|
|
2506
|
-
lines.push(
|
|
2556
|
+
lines.push(
|
|
2557
|
+
`- ${ensureHandlePrefix(participantHandle) ?? ""} \u2014 ${participantName} (${participantType})`
|
|
2558
|
+
);
|
|
2507
2559
|
}
|
|
2508
2560
|
lines.push("");
|
|
2509
2561
|
lines.push(
|
|
@@ -2982,7 +3034,7 @@ var AgentRuntime = class {
|
|
|
2982
3034
|
await this.link.disconnect();
|
|
2983
3035
|
}
|
|
2984
3036
|
async stop(timeoutMs) {
|
|
2985
|
-
if (!this.running
|
|
3037
|
+
if (this.stopping || !this.running && !this.fatalError) {
|
|
2986
3038
|
return true;
|
|
2987
3039
|
}
|
|
2988
3040
|
this.stopping = true;
|
|
@@ -3002,7 +3054,8 @@ var AgentRuntime = class {
|
|
|
3002
3054
|
}
|
|
3003
3055
|
}
|
|
3004
3056
|
for (const roomId of [...this.subscribedRooms]) {
|
|
3005
|
-
|
|
3057
|
+
const remaining = deadline === void 0 ? void 0 : Math.max(0, deadline - Date.now());
|
|
3058
|
+
await this.leaveTrackedRoom(roomId, remaining);
|
|
3006
3059
|
}
|
|
3007
3060
|
for (const roomId of [...this.contexts.keys()]) {
|
|
3008
3061
|
await this.onSessionCleanup(roomId);
|
|
@@ -3038,7 +3091,13 @@ var AgentRuntime = class {
|
|
|
3038
3091
|
}
|
|
3039
3092
|
async consumeLoop(signal) {
|
|
3040
3093
|
while (!signal.aborted) {
|
|
3041
|
-
|
|
3094
|
+
let event;
|
|
3095
|
+
try {
|
|
3096
|
+
event = await this.link.nextEvent(signal);
|
|
3097
|
+
} catch (error) {
|
|
3098
|
+
await this.failRuntime(error, syntheticRuntimeFailureEvent(this.agentId));
|
|
3099
|
+
return;
|
|
3100
|
+
}
|
|
3042
3101
|
if (!event) {
|
|
3043
3102
|
return;
|
|
3044
3103
|
}
|
|
@@ -3201,13 +3260,13 @@ var AgentRuntime = class {
|
|
|
3201
3260
|
}
|
|
3202
3261
|
});
|
|
3203
3262
|
}
|
|
3204
|
-
async leaveTrackedRoom(roomId) {
|
|
3263
|
+
async leaveTrackedRoom(roomId, timeoutMs) {
|
|
3205
3264
|
await trackRoomLeave({
|
|
3206
3265
|
link: this.link,
|
|
3207
3266
|
roomId,
|
|
3208
3267
|
trackedRooms: this.subscribedRooms,
|
|
3209
3268
|
onLeft: async (leftRoomId) => {
|
|
3210
|
-
await this.executions.get(leftRoomId)?.stop();
|
|
3269
|
+
await this.executions.get(leftRoomId)?.stop(timeoutMs);
|
|
3211
3270
|
this.contexts.delete(leftRoomId);
|
|
3212
3271
|
this.executions.delete(leftRoomId);
|
|
3213
3272
|
await this.onSessionCleanup(leftRoomId);
|
|
@@ -3244,6 +3303,23 @@ var AgentRuntime = class {
|
|
|
3244
3303
|
}
|
|
3245
3304
|
}
|
|
3246
3305
|
};
|
|
3306
|
+
function syntheticRuntimeFailureEvent(agentId) {
|
|
3307
|
+
return {
|
|
3308
|
+
type: "message_created",
|
|
3309
|
+
roomId: null,
|
|
3310
|
+
payload: {
|
|
3311
|
+
id: "runtime-failed",
|
|
3312
|
+
content: "",
|
|
3313
|
+
sender_id: agentId,
|
|
3314
|
+
sender_type: "Agent",
|
|
3315
|
+
sender_name: null,
|
|
3316
|
+
message_type: "text",
|
|
3317
|
+
metadata: {},
|
|
3318
|
+
inserted_at: (/* @__PURE__ */ new Date(0)).toISOString(),
|
|
3319
|
+
updated_at: (/* @__PURE__ */ new Date(0)).toISOString()
|
|
3320
|
+
}
|
|
3321
|
+
};
|
|
3322
|
+
}
|
|
3247
3323
|
function assertNever2(value) {
|
|
3248
3324
|
throw new Error(`Unhandled platform event: ${JSON.stringify(value)}`);
|
|
3249
3325
|
}
|
|
@@ -4185,55 +4261,241 @@ var payloadSchemas = {
|
|
|
4185
4261
|
|
|
4186
4262
|
// src/platform/streaming/PhoenixChannelsTransport.ts
|
|
4187
4263
|
var import_phoenix = require("phoenix");
|
|
4264
|
+
|
|
4265
|
+
// src/platform/streaming/disconnectReason.ts
|
|
4266
|
+
var import_zod2 = require("zod");
|
|
4267
|
+
var UPGRADE_CODES = [
|
|
4268
|
+
"invalid_on_conflict",
|
|
4269
|
+
"connection_conflict",
|
|
4270
|
+
"too_many_requests",
|
|
4271
|
+
"tracking_failed"
|
|
4272
|
+
];
|
|
4273
|
+
var UPGRADE_REASONS = {
|
|
4274
|
+
invalid_on_conflict: {
|
|
4275
|
+
status: 400,
|
|
4276
|
+
message: "Invalid websocket conflict policy.",
|
|
4277
|
+
retryable: false
|
|
4278
|
+
},
|
|
4279
|
+
connection_conflict: {
|
|
4280
|
+
status: 409,
|
|
4281
|
+
message: "Websocket connection conflict.",
|
|
4282
|
+
retryable: false
|
|
4283
|
+
},
|
|
4284
|
+
too_many_requests: {
|
|
4285
|
+
status: 429,
|
|
4286
|
+
message: "Too many websocket connection attempts.",
|
|
4287
|
+
retryable: true
|
|
4288
|
+
},
|
|
4289
|
+
tracking_failed: {
|
|
4290
|
+
status: 503,
|
|
4291
|
+
message: "Websocket connection tracking failed.",
|
|
4292
|
+
retryable: true
|
|
4293
|
+
}
|
|
4294
|
+
};
|
|
4295
|
+
var upgradeErrorSchema = import_zod2.z.object({
|
|
4296
|
+
status: import_zod2.z.number(),
|
|
4297
|
+
body: import_zod2.z.preprocess(
|
|
4298
|
+
(body) => {
|
|
4299
|
+
if (typeof body !== "string") {
|
|
4300
|
+
return body;
|
|
4301
|
+
}
|
|
4302
|
+
try {
|
|
4303
|
+
return JSON.parse(body);
|
|
4304
|
+
} catch {
|
|
4305
|
+
return null;
|
|
4306
|
+
}
|
|
4307
|
+
},
|
|
4308
|
+
import_zod2.z.object({
|
|
4309
|
+
error: import_zod2.z.object({
|
|
4310
|
+
code: import_zod2.z.enum(UPGRADE_CODES),
|
|
4311
|
+
message: import_zod2.z.string().optional(),
|
|
4312
|
+
retry_after: import_zod2.z.number().nullable().optional(),
|
|
4313
|
+
request_id: import_zod2.z.string().nullable().optional()
|
|
4314
|
+
})
|
|
4315
|
+
})
|
|
4316
|
+
),
|
|
4317
|
+
headers: import_zod2.z.record(import_zod2.z.unknown()).optional()
|
|
4318
|
+
});
|
|
4319
|
+
var WebSocketDisconnectError = class extends Error {
|
|
4320
|
+
reason;
|
|
4321
|
+
constructor(reason) {
|
|
4322
|
+
super(reason.message);
|
|
4323
|
+
this.name = "WebSocketDisconnectError";
|
|
4324
|
+
this.reason = reason;
|
|
4325
|
+
}
|
|
4326
|
+
};
|
|
4327
|
+
function parseSupersedeDisconnectReason(payload) {
|
|
4328
|
+
if (typeof payload.reason !== "string" || typeof payload.message !== "string") {
|
|
4329
|
+
return null;
|
|
4330
|
+
}
|
|
4331
|
+
return {
|
|
4332
|
+
source: "agent_control",
|
|
4333
|
+
code: payload.reason,
|
|
4334
|
+
message: payload.message,
|
|
4335
|
+
retryable: false,
|
|
4336
|
+
retryAfter: typeof payload.retry_after === "number" ? payload.retry_after : null,
|
|
4337
|
+
targetSocketId: typeof payload.target_socket_id === "string" ? payload.target_socket_id : null,
|
|
4338
|
+
correlationId: typeof payload.correlation_id === "string" ? payload.correlation_id : null
|
|
4339
|
+
};
|
|
4340
|
+
}
|
|
4341
|
+
function parseUpgradeDisconnectReason(event) {
|
|
4342
|
+
const parsed = upgradeErrorSchema.safeParse(event);
|
|
4343
|
+
if (!parsed.success) {
|
|
4344
|
+
return null;
|
|
4345
|
+
}
|
|
4346
|
+
const { status, body, headers } = parsed.data;
|
|
4347
|
+
const {
|
|
4348
|
+
code,
|
|
4349
|
+
message,
|
|
4350
|
+
retry_after: retryAfter,
|
|
4351
|
+
request_id: requestId
|
|
4352
|
+
} = body.error;
|
|
4353
|
+
const reason = UPGRADE_REASONS[code];
|
|
4354
|
+
if (status !== reason.status) {
|
|
4355
|
+
return null;
|
|
4356
|
+
}
|
|
4357
|
+
return {
|
|
4358
|
+
source: "upgrade",
|
|
4359
|
+
status: reason.status,
|
|
4360
|
+
code,
|
|
4361
|
+
message: message ?? reason.message,
|
|
4362
|
+
retryable: reason.retryable,
|
|
4363
|
+
retryAfter: retryAfter ?? retryAfterFromHeaders(headers),
|
|
4364
|
+
requestId: requestId ?? null
|
|
4365
|
+
};
|
|
4366
|
+
}
|
|
4367
|
+
function genericCloseReason(event) {
|
|
4368
|
+
return {
|
|
4369
|
+
source: "websocket_close",
|
|
4370
|
+
code: "websocket.closed",
|
|
4371
|
+
message: "Phoenix socket closed without a platform disconnect reason.",
|
|
4372
|
+
retryable: true,
|
|
4373
|
+
closeCode: typeof event?.code === "number" ? event.code : null,
|
|
4374
|
+
closeReason: typeof event?.reason === "string" && event.reason.length > 0 ? event.reason : null
|
|
4375
|
+
};
|
|
4376
|
+
}
|
|
4377
|
+
function retryAfterFromHeaders(headers) {
|
|
4378
|
+
const value = headers?.["retry-after"] ?? headers?.["Retry-After"];
|
|
4379
|
+
if (typeof value === "number") {
|
|
4380
|
+
return value;
|
|
4381
|
+
}
|
|
4382
|
+
if (typeof value === "string" && value.trim() !== "") {
|
|
4383
|
+
const seconds = Number(value);
|
|
4384
|
+
return Number.isFinite(seconds) ? seconds : null;
|
|
4385
|
+
}
|
|
4386
|
+
return null;
|
|
4387
|
+
}
|
|
4388
|
+
|
|
4389
|
+
// src/platform/streaming/nodeWebSocketFactory.ts
|
|
4188
4390
|
var import_ws = require("ws");
|
|
4391
|
+
function createNodeWebSocketFactory(headers) {
|
|
4392
|
+
const Constructor = import_ws.WebSocket;
|
|
4393
|
+
class ThenvoiNodeWebSocket {
|
|
4394
|
+
constructor(address, protocols) {
|
|
4395
|
+
const socket = new Constructor(address, protocols, headers ? { headers } : void 0);
|
|
4396
|
+
socket.once("unexpected-response", (request, response) => {
|
|
4397
|
+
void emitUpgradeError(socket, request, response);
|
|
4398
|
+
});
|
|
4399
|
+
return socket;
|
|
4400
|
+
}
|
|
4401
|
+
}
|
|
4402
|
+
return ThenvoiNodeWebSocket;
|
|
4403
|
+
}
|
|
4404
|
+
async function emitUpgradeError(websocket, request, response) {
|
|
4405
|
+
const body = await readResponseBody(response);
|
|
4406
|
+
const error = new Error(
|
|
4407
|
+
`Unexpected server response: ${response.statusCode ?? "unknown"}`
|
|
4408
|
+
);
|
|
4409
|
+
error.status = response.statusCode;
|
|
4410
|
+
error.body = body;
|
|
4411
|
+
error.headers = response.headers;
|
|
4412
|
+
request.destroy();
|
|
4413
|
+
websocket.emit("error", error);
|
|
4414
|
+
websocket.emit("close", 1006, Buffer.alloc(0));
|
|
4415
|
+
}
|
|
4416
|
+
async function readResponseBody(response) {
|
|
4417
|
+
const chunks = [];
|
|
4418
|
+
for await (const chunk of response) {
|
|
4419
|
+
chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
|
|
4420
|
+
}
|
|
4421
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
4422
|
+
}
|
|
4423
|
+
|
|
4424
|
+
// src/platform/streaming/PhoenixChannelsTransport.ts
|
|
4189
4425
|
var PhoenixChannelsTransport = class {
|
|
4190
4426
|
socket;
|
|
4427
|
+
agentId;
|
|
4191
4428
|
channels = /* @__PURE__ */ new Map();
|
|
4192
4429
|
channelRefs = /* @__PURE__ */ new Map();
|
|
4193
4430
|
pendingJoins = /* @__PURE__ */ new Map();
|
|
4194
4431
|
logger;
|
|
4432
|
+
onTerminalDisconnect;
|
|
4195
4433
|
onHandlerError;
|
|
4196
4434
|
connected = false;
|
|
4197
4435
|
connectPromise = null;
|
|
4198
4436
|
connectResolve = null;
|
|
4437
|
+
connectReject = null;
|
|
4438
|
+
lastDisconnectReason = null;
|
|
4439
|
+
terminalDisconnectError = null;
|
|
4440
|
+
runForeverWaiters = /* @__PURE__ */ new Set();
|
|
4441
|
+
stoppingReconnect = false;
|
|
4442
|
+
suppressNextCloseReason = false;
|
|
4199
4443
|
constructor(options) {
|
|
4200
4444
|
this.logger = options.logger ?? new NoopLogger();
|
|
4445
|
+
this.agentId = options.agentId;
|
|
4446
|
+
this.onTerminalDisconnect = options.onTerminalDisconnect;
|
|
4201
4447
|
let wsUrl = options.wsUrl;
|
|
4202
4448
|
if (wsUrl.endsWith("/websocket")) {
|
|
4203
4449
|
wsUrl = wsUrl.slice(0, -"/websocket".length);
|
|
4204
4450
|
}
|
|
4451
|
+
const reconnectAfterMs = options.reconnectAfterMs ?? ((tries) => [1e3, 2e3, 5e3, 1e4, 3e4][tries - 1] ?? 3e4);
|
|
4205
4452
|
this.socket = new import_phoenix.Socket(wsUrl, {
|
|
4206
4453
|
params: {
|
|
4207
|
-
|
|
4208
|
-
|
|
4454
|
+
agent_id: options.agentId,
|
|
4455
|
+
...options.conflictPolicy ? { on_conflict: options.conflictPolicy } : {}
|
|
4209
4456
|
},
|
|
4210
4457
|
heartbeatIntervalMs: options.heartbeatIntervalMs,
|
|
4211
|
-
reconnectAfterMs:
|
|
4212
|
-
|
|
4458
|
+
reconnectAfterMs: (tries) => {
|
|
4459
|
+
if (this.terminalDisconnectError) {
|
|
4460
|
+
return Number.POSITIVE_INFINITY;
|
|
4461
|
+
}
|
|
4462
|
+
return reconnectAfterMs(tries);
|
|
4463
|
+
},
|
|
4464
|
+
transport: options.websocketFactory ?? resolveWebSocketFactory(options.apiKey)
|
|
4213
4465
|
});
|
|
4214
4466
|
this.socket.onOpen(() => {
|
|
4215
|
-
this.
|
|
4216
|
-
this.connectResolve?.();
|
|
4217
|
-
this.connectResolve = null;
|
|
4218
|
-
this.logger.info("Phoenix socket opened", {
|
|
4219
|
-
channels: getSocketChannelCount(this.socket)
|
|
4220
|
-
});
|
|
4467
|
+
void this.handleOpen();
|
|
4221
4468
|
});
|
|
4222
4469
|
this.socket.onClose((event) => {
|
|
4223
|
-
this.
|
|
4224
|
-
if (getSocketChannelCount(this.socket) === 0) {
|
|
4225
|
-
this.socket.disconnect();
|
|
4226
|
-
}
|
|
4227
|
-
this.logger.info("Phoenix socket closed", {
|
|
4228
|
-
code: event?.code ?? null,
|
|
4229
|
-
reason: event?.reason ?? null
|
|
4230
|
-
});
|
|
4470
|
+
this.recordSocketClose(event);
|
|
4231
4471
|
});
|
|
4232
4472
|
this.socket.onError((event) => {
|
|
4473
|
+
const errorEvent = unwrapErrorEvent(event);
|
|
4474
|
+
const upgradeReason = parseUpgradeDisconnectReason(errorEvent);
|
|
4475
|
+
if (upgradeReason) {
|
|
4476
|
+
if (upgradeReason.retryable) {
|
|
4477
|
+
this.lastDisconnectReason = upgradeReason;
|
|
4478
|
+
this.connectReject?.(new WebSocketDisconnectError(upgradeReason));
|
|
4479
|
+
this.stopReconnectIfNoChannels({ suppressCloseReason: true });
|
|
4480
|
+
} else {
|
|
4481
|
+
this.recordTerminalDisconnect(upgradeReason);
|
|
4482
|
+
}
|
|
4483
|
+
this.logger.warn("Phoenix socket upgrade failed", {
|
|
4484
|
+
reason: upgradeReason
|
|
4485
|
+
});
|
|
4486
|
+
return;
|
|
4487
|
+
}
|
|
4488
|
+
this.connectReject?.(
|
|
4489
|
+
new TransportError("Phoenix socket connection failed", errorEvent)
|
|
4490
|
+
);
|
|
4491
|
+
this.stopReconnectIfNoChannels({ suppressCloseReason: true });
|
|
4233
4492
|
this.logger.warn("Phoenix socket error", { event });
|
|
4234
4493
|
});
|
|
4235
4494
|
}
|
|
4236
4495
|
async connect() {
|
|
4496
|
+
if (this.terminalDisconnectError) {
|
|
4497
|
+
throw this.terminalDisconnectError;
|
|
4498
|
+
}
|
|
4237
4499
|
if (this.connected) {
|
|
4238
4500
|
return;
|
|
4239
4501
|
}
|
|
@@ -4257,15 +4519,30 @@ var PhoenixChannelsTransport = class {
|
|
|
4257
4519
|
await this.connectPromise;
|
|
4258
4520
|
}
|
|
4259
4521
|
async disconnect() {
|
|
4260
|
-
|
|
4261
|
-
|
|
4262
|
-
|
|
4522
|
+
const results = await Promise.allSettled(
|
|
4523
|
+
[...this.channels.keys()].map((topic) => this.leave(topic))
|
|
4524
|
+
);
|
|
4263
4525
|
this.socket.disconnect();
|
|
4264
4526
|
this.connected = false;
|
|
4527
|
+
const failures = [];
|
|
4528
|
+
for (const result of results) {
|
|
4529
|
+
if (result.status === "rejected") {
|
|
4530
|
+
failures.push(result.reason);
|
|
4531
|
+
}
|
|
4532
|
+
}
|
|
4533
|
+
if (failures.length > 0) {
|
|
4534
|
+
throw new AggregateError(
|
|
4535
|
+
failures,
|
|
4536
|
+
"Failed to leave one or more Phoenix topics during disconnect"
|
|
4537
|
+
);
|
|
4538
|
+
}
|
|
4265
4539
|
}
|
|
4266
4540
|
isConnected() {
|
|
4267
4541
|
return this.connected;
|
|
4268
4542
|
}
|
|
4543
|
+
getDisconnectReason() {
|
|
4544
|
+
return this.lastDisconnectReason;
|
|
4545
|
+
}
|
|
4269
4546
|
async join(topic, handlers) {
|
|
4270
4547
|
if (this.channels.has(topic)) {
|
|
4271
4548
|
return;
|
|
@@ -4301,7 +4578,10 @@ var PhoenixChannelsTransport = class {
|
|
|
4301
4578
|
channel.join().receive("ok", () => resolve()).receive(
|
|
4302
4579
|
"error",
|
|
4303
4580
|
(error) => reject(new TransportError(`Failed to join topic ${topic}`, error))
|
|
4304
|
-
).receive(
|
|
4581
|
+
).receive(
|
|
4582
|
+
"timeout",
|
|
4583
|
+
() => reject(new TransportError(`Timeout joining topic ${topic}`))
|
|
4584
|
+
);
|
|
4305
4585
|
});
|
|
4306
4586
|
} catch (error) {
|
|
4307
4587
|
for (const [event, ref] of refs) {
|
|
@@ -4329,19 +4609,127 @@ var PhoenixChannelsTransport = class {
|
|
|
4329
4609
|
channel.leave().receive("ok", () => resolve()).receive(
|
|
4330
4610
|
"error",
|
|
4331
4611
|
(error) => reject(new TransportError(`Failed to leave topic ${topic}`, error))
|
|
4332
|
-
).receive(
|
|
4612
|
+
).receive(
|
|
4613
|
+
"timeout",
|
|
4614
|
+
() => reject(new TransportError(`Timeout leaving topic ${topic}`))
|
|
4615
|
+
);
|
|
4333
4616
|
});
|
|
4334
4617
|
this.channels.delete(topic);
|
|
4335
4618
|
this.logger.debug("Left topic", { topic });
|
|
4336
4619
|
}
|
|
4337
4620
|
async runForever(signal) {
|
|
4621
|
+
if (this.terminalDisconnectError) {
|
|
4622
|
+
throw this.terminalDisconnectError;
|
|
4623
|
+
}
|
|
4338
4624
|
if (signal.aborted) {
|
|
4339
4625
|
return;
|
|
4340
4626
|
}
|
|
4341
|
-
await new Promise((resolve) => {
|
|
4342
|
-
|
|
4627
|
+
await new Promise((resolve, reject) => {
|
|
4628
|
+
let settled = false;
|
|
4629
|
+
const abortController = new AbortController();
|
|
4630
|
+
const waiter = {
|
|
4631
|
+
reject: (error) => {
|
|
4632
|
+
if (settled) {
|
|
4633
|
+
return;
|
|
4634
|
+
}
|
|
4635
|
+
settled = true;
|
|
4636
|
+
this.runForeverWaiters.delete(waiter);
|
|
4637
|
+
abortController.abort();
|
|
4638
|
+
reject(error);
|
|
4639
|
+
}
|
|
4640
|
+
};
|
|
4641
|
+
this.runForeverWaiters.add(waiter);
|
|
4642
|
+
signal.addEventListener(
|
|
4643
|
+
"abort",
|
|
4644
|
+
() => {
|
|
4645
|
+
if (settled) {
|
|
4646
|
+
return;
|
|
4647
|
+
}
|
|
4648
|
+
settled = true;
|
|
4649
|
+
this.runForeverWaiters.delete(waiter);
|
|
4650
|
+
resolve();
|
|
4651
|
+
},
|
|
4652
|
+
{ once: true, signal: abortController.signal }
|
|
4653
|
+
);
|
|
4654
|
+
});
|
|
4655
|
+
}
|
|
4656
|
+
async handleOpen() {
|
|
4657
|
+
try {
|
|
4658
|
+
await this.subscribeAgentControl();
|
|
4659
|
+
} catch (error) {
|
|
4660
|
+
this.connected = false;
|
|
4661
|
+
this.socket.disconnect();
|
|
4662
|
+
this.connectReject?.(
|
|
4663
|
+
error instanceof Error ? error : new TransportError(String(error))
|
|
4664
|
+
);
|
|
4665
|
+
this.logger.warn("Failed to join mandatory agent_control channel", {
|
|
4666
|
+
error
|
|
4667
|
+
});
|
|
4668
|
+
return;
|
|
4669
|
+
}
|
|
4670
|
+
this.connected = true;
|
|
4671
|
+
this.connectResolve?.();
|
|
4672
|
+
this.connectResolve = null;
|
|
4673
|
+
this.connectReject = null;
|
|
4674
|
+
this.logger.info("Phoenix socket opened", {
|
|
4675
|
+
channels: getSocketChannelCount(this.socket)
|
|
4343
4676
|
});
|
|
4344
4677
|
}
|
|
4678
|
+
stopReconnectIfNoChannels(options = {}) {
|
|
4679
|
+
if (this.stoppingReconnect || getSocketChannelCount(this.socket) !== 0) {
|
|
4680
|
+
return;
|
|
4681
|
+
}
|
|
4682
|
+
this.suppressNextCloseReason = options.suppressCloseReason ?? false;
|
|
4683
|
+
this.stoppingReconnect = true;
|
|
4684
|
+
this.socket.disconnect();
|
|
4685
|
+
this.stoppingReconnect = false;
|
|
4686
|
+
}
|
|
4687
|
+
async subscribeAgentControl() {
|
|
4688
|
+
if (!this.agentId) {
|
|
4689
|
+
return;
|
|
4690
|
+
}
|
|
4691
|
+
await this.join(`agent_control:${this.agentId}`, {
|
|
4692
|
+
supersede: (payload) => {
|
|
4693
|
+
const reason = parseSupersedeDisconnectReason(payload);
|
|
4694
|
+
if (!reason) {
|
|
4695
|
+
this.logger.warn("Invalid agent_control supersede payload", {
|
|
4696
|
+
payload
|
|
4697
|
+
});
|
|
4698
|
+
return;
|
|
4699
|
+
}
|
|
4700
|
+
this.recordTerminalDisconnect(reason);
|
|
4701
|
+
}
|
|
4702
|
+
});
|
|
4703
|
+
}
|
|
4704
|
+
recordSocketClose(event) {
|
|
4705
|
+
this.connected = false;
|
|
4706
|
+
const suppressCloseReason = this.suppressNextCloseReason;
|
|
4707
|
+
this.suppressNextCloseReason = false;
|
|
4708
|
+
this.stopReconnectIfNoChannels();
|
|
4709
|
+
if (!suppressCloseReason && !this.terminalDisconnectError && !this.lastDisconnectReason) {
|
|
4710
|
+
this.lastDisconnectReason = genericCloseReason(event);
|
|
4711
|
+
}
|
|
4712
|
+
this.logger.info("Phoenix socket closed", {
|
|
4713
|
+
code: event?.code ?? null,
|
|
4714
|
+
reason: event?.reason ?? null,
|
|
4715
|
+
platformReason: this.lastDisconnectReason
|
|
4716
|
+
});
|
|
4717
|
+
}
|
|
4718
|
+
recordTerminalDisconnect(reason) {
|
|
4719
|
+
if (this.terminalDisconnectError) {
|
|
4720
|
+
return;
|
|
4721
|
+
}
|
|
4722
|
+
const error = new WebSocketDisconnectError(reason);
|
|
4723
|
+
this.lastDisconnectReason = reason;
|
|
4724
|
+
this.terminalDisconnectError = error;
|
|
4725
|
+
this.onTerminalDisconnect?.(reason);
|
|
4726
|
+
this.connectReject?.(error);
|
|
4727
|
+
for (const waiter of this.runForeverWaiters) {
|
|
4728
|
+
waiter.reject(error);
|
|
4729
|
+
}
|
|
4730
|
+
this.runForeverWaiters.clear();
|
|
4731
|
+
this.socket.disconnect();
|
|
4732
|
+
}
|
|
4345
4733
|
async waitForConnection(timeoutMs = 1e4) {
|
|
4346
4734
|
if (this.connected) {
|
|
4347
4735
|
return;
|
|
@@ -4349,20 +4737,43 @@ var PhoenixChannelsTransport = class {
|
|
|
4349
4737
|
await new Promise((resolve, reject) => {
|
|
4350
4738
|
const timeout = setTimeout(() => {
|
|
4351
4739
|
this.connectResolve = null;
|
|
4352
|
-
|
|
4740
|
+
this.connectReject = null;
|
|
4741
|
+
reject(
|
|
4742
|
+
new TransportError("Timed out waiting for Phoenix socket connection")
|
|
4743
|
+
);
|
|
4353
4744
|
}, timeoutMs);
|
|
4354
4745
|
this.connectResolve = () => {
|
|
4355
4746
|
clearTimeout(timeout);
|
|
4747
|
+
this.connectReject = null;
|
|
4356
4748
|
resolve();
|
|
4357
4749
|
};
|
|
4750
|
+
this.connectReject = (error) => {
|
|
4751
|
+
clearTimeout(timeout);
|
|
4752
|
+
this.connectResolve = null;
|
|
4753
|
+
this.connectReject = null;
|
|
4754
|
+
reject(
|
|
4755
|
+
error instanceof Error ? error : new TransportError(String(error))
|
|
4756
|
+
);
|
|
4757
|
+
};
|
|
4358
4758
|
});
|
|
4359
4759
|
}
|
|
4360
4760
|
};
|
|
4361
|
-
function resolveWebSocketFactory() {
|
|
4761
|
+
function resolveWebSocketFactory(apiKey) {
|
|
4362
4762
|
if (typeof process !== "undefined" && process.versions?.node) {
|
|
4363
|
-
return
|
|
4763
|
+
return createNodeWebSocketFactory({ "x-api-key": apiKey });
|
|
4764
|
+
}
|
|
4765
|
+
throw new TransportError(
|
|
4766
|
+
"Phoenix WebSocket API-key auth requires a WebSocket transport that can set handshake headers."
|
|
4767
|
+
);
|
|
4768
|
+
}
|
|
4769
|
+
function unwrapErrorEvent(event) {
|
|
4770
|
+
if (!isErrorEvent(event)) {
|
|
4771
|
+
return event;
|
|
4364
4772
|
}
|
|
4365
|
-
return
|
|
4773
|
+
return event.error;
|
|
4774
|
+
}
|
|
4775
|
+
function isErrorEvent(event) {
|
|
4776
|
+
return typeof event === "object" && event !== null && "error" in event;
|
|
4366
4777
|
}
|
|
4367
4778
|
function removeSocketChannel(socket, channel) {
|
|
4368
4779
|
const candidate = socket;
|
|
@@ -4384,6 +4795,12 @@ function deriveDefaultRestUrl(wsUrl) {
|
|
|
4384
4795
|
const protocol = parsed.protocol === "ws:" ? "http:" : "https:";
|
|
4385
4796
|
return `${protocol}//${parsed.host}`;
|
|
4386
4797
|
}
|
|
4798
|
+
function roomTopics(roomId) {
|
|
4799
|
+
return {
|
|
4800
|
+
chat: `chat_room:${roomId}`,
|
|
4801
|
+
participants: `room_participants:${roomId}`
|
|
4802
|
+
};
|
|
4803
|
+
}
|
|
4387
4804
|
function toPlatformMessage(roomId, message) {
|
|
4388
4805
|
return {
|
|
4389
4806
|
id: message.id,
|
|
@@ -4410,6 +4827,8 @@ var ThenvoiLink = class {
|
|
|
4410
4827
|
eventQueue = [];
|
|
4411
4828
|
waiters = [];
|
|
4412
4829
|
connected = false;
|
|
4830
|
+
lastDisconnectReason = null;
|
|
4831
|
+
terminalDisconnectError = null;
|
|
4413
4832
|
constructor(options) {
|
|
4414
4833
|
this.agentId = options.agentId;
|
|
4415
4834
|
this.apiKey = options.apiKey;
|
|
@@ -4431,17 +4850,35 @@ var ThenvoiLink = class {
|
|
|
4431
4850
|
wsUrl: this.wsUrl,
|
|
4432
4851
|
apiKey: this.apiKey,
|
|
4433
4852
|
agentId: this.agentId,
|
|
4434
|
-
logger: this.logger
|
|
4853
|
+
logger: this.logger,
|
|
4854
|
+
conflictPolicy: options.conflictPolicy,
|
|
4855
|
+
onTerminalDisconnect: (reason) => {
|
|
4856
|
+
this.recordDisconnectReason(reason);
|
|
4857
|
+
}
|
|
4435
4858
|
});
|
|
4436
4859
|
}
|
|
4437
4860
|
isConnected() {
|
|
4438
4861
|
return this.connected;
|
|
4439
4862
|
}
|
|
4863
|
+
getDisconnectReason() {
|
|
4864
|
+
return this.lastDisconnectReason;
|
|
4865
|
+
}
|
|
4440
4866
|
async connect() {
|
|
4441
4867
|
if (this.connected) {
|
|
4442
4868
|
return;
|
|
4443
4869
|
}
|
|
4444
|
-
|
|
4870
|
+
try {
|
|
4871
|
+
await this.transport.connect();
|
|
4872
|
+
} catch (error) {
|
|
4873
|
+
if (error instanceof WebSocketDisconnectError) {
|
|
4874
|
+
if (error.reason.retryable) {
|
|
4875
|
+
this.lastDisconnectReason = error.reason;
|
|
4876
|
+
} else {
|
|
4877
|
+
this.recordDisconnectError(error);
|
|
4878
|
+
}
|
|
4879
|
+
}
|
|
4880
|
+
throw error;
|
|
4881
|
+
}
|
|
4445
4882
|
this.connected = true;
|
|
4446
4883
|
}
|
|
4447
4884
|
async disconnect() {
|
|
@@ -4455,8 +4892,23 @@ var ThenvoiLink = class {
|
|
|
4455
4892
|
this.connected = false;
|
|
4456
4893
|
}
|
|
4457
4894
|
async runForever(signal) {
|
|
4895
|
+
if (this.terminalDisconnectError) {
|
|
4896
|
+
throw this.terminalDisconnectError;
|
|
4897
|
+
}
|
|
4458
4898
|
await this.transport.runForever(signal);
|
|
4459
4899
|
}
|
|
4900
|
+
recordDisconnectReason(reason) {
|
|
4901
|
+
this.recordDisconnectError(new WebSocketDisconnectError(reason));
|
|
4902
|
+
}
|
|
4903
|
+
recordDisconnectError(error) {
|
|
4904
|
+
this.connected = false;
|
|
4905
|
+
this.lastDisconnectReason = error.reason;
|
|
4906
|
+
this.terminalDisconnectError = error;
|
|
4907
|
+
while (this.waiters.length > 0) {
|
|
4908
|
+
const waiter = this.waiters.shift();
|
|
4909
|
+
waiter?.reject(error);
|
|
4910
|
+
}
|
|
4911
|
+
}
|
|
4460
4912
|
queueEvent(event) {
|
|
4461
4913
|
const waiter = this.waiters.shift();
|
|
4462
4914
|
if (waiter) {
|
|
@@ -4481,32 +4933,42 @@ var ThenvoiLink = class {
|
|
|
4481
4933
|
if (this.subscribedRooms.has(roomId)) {
|
|
4482
4934
|
return;
|
|
4483
4935
|
}
|
|
4484
|
-
await this.
|
|
4485
|
-
message_created: (payload) => {
|
|
4486
|
-
this.emit("message_created", payload, roomId);
|
|
4487
|
-
}
|
|
4488
|
-
});
|
|
4489
|
-
await this.transport.join(`room_participants:${roomId}`, {
|
|
4490
|
-
participant_added: (payload) => {
|
|
4491
|
-
this.emit("participant_added", payload, roomId);
|
|
4492
|
-
},
|
|
4493
|
-
participant_removed: (payload) => {
|
|
4494
|
-
this.emit("participant_removed", payload, roomId);
|
|
4495
|
-
},
|
|
4496
|
-
room_deleted: (payload) => {
|
|
4497
|
-
this.emit("room_deleted", payload, roomId);
|
|
4498
|
-
}
|
|
4499
|
-
});
|
|
4936
|
+
await this.joinRoomTopics(roomId);
|
|
4500
4937
|
this.subscribedRooms.add(roomId);
|
|
4501
4938
|
}
|
|
4502
4939
|
async unsubscribeRoom(roomId) {
|
|
4503
4940
|
if (!this.subscribedRooms.has(roomId)) {
|
|
4504
4941
|
return;
|
|
4505
4942
|
}
|
|
4506
|
-
|
|
4507
|
-
await this.transport.leave(
|
|
4943
|
+
const topics = roomTopics(roomId);
|
|
4944
|
+
await this.transport.leave(topics.chat);
|
|
4945
|
+
await this.transport.leave(topics.participants);
|
|
4508
4946
|
this.subscribedRooms.delete(roomId);
|
|
4509
4947
|
}
|
|
4948
|
+
async joinRoomTopics(roomId) {
|
|
4949
|
+
const topics = roomTopics(roomId);
|
|
4950
|
+
await this.transport.join(topics.chat, {
|
|
4951
|
+
message_created: (payload) => {
|
|
4952
|
+
this.emit("message_created", payload, roomId);
|
|
4953
|
+
}
|
|
4954
|
+
});
|
|
4955
|
+
try {
|
|
4956
|
+
await this.transport.join(topics.participants, {
|
|
4957
|
+
participant_added: (payload) => {
|
|
4958
|
+
this.emit("participant_added", payload, roomId);
|
|
4959
|
+
},
|
|
4960
|
+
participant_removed: (payload) => {
|
|
4961
|
+
this.emit("participant_removed", payload, roomId);
|
|
4962
|
+
},
|
|
4963
|
+
room_deleted: (payload) => {
|
|
4964
|
+
this.emit("room_deleted", payload, roomId);
|
|
4965
|
+
}
|
|
4966
|
+
});
|
|
4967
|
+
} catch (error) {
|
|
4968
|
+
await this.transport.leave(topics.chat);
|
|
4969
|
+
throw error;
|
|
4970
|
+
}
|
|
4971
|
+
}
|
|
4510
4972
|
async subscribeAgentContacts() {
|
|
4511
4973
|
assertCapability(this.capabilities, "contacts", "Contacts streaming");
|
|
4512
4974
|
await this.transport.join(`agent_contacts:${this.agentId}`, {
|
|
@@ -4528,6 +4990,9 @@ var ThenvoiLink = class {
|
|
|
4528
4990
|
await this.transport.leave(`agent_contacts:${this.agentId}`);
|
|
4529
4991
|
}
|
|
4530
4992
|
async nextEvent(signal) {
|
|
4993
|
+
if (this.terminalDisconnectError) {
|
|
4994
|
+
throw this.terminalDisconnectError;
|
|
4995
|
+
}
|
|
4531
4996
|
if (signal?.aborted) {
|
|
4532
4997
|
return null;
|
|
4533
4998
|
}
|
|
@@ -4535,19 +5000,19 @@ var ThenvoiLink = class {
|
|
|
4535
5000
|
if (queued) {
|
|
4536
5001
|
return queued;
|
|
4537
5002
|
}
|
|
4538
|
-
return new Promise((resolve) => {
|
|
5003
|
+
return new Promise((resolve, reject) => {
|
|
4539
5004
|
let settled = false;
|
|
4540
5005
|
const onAbort = () => {
|
|
4541
5006
|
const index = this.waiters.indexOf(waiter);
|
|
4542
5007
|
if (index >= 0) {
|
|
4543
5008
|
this.waiters.splice(index, 1);
|
|
4544
5009
|
}
|
|
4545
|
-
|
|
5010
|
+
finalizeResolve(null);
|
|
4546
5011
|
};
|
|
4547
5012
|
const cleanup = () => {
|
|
4548
5013
|
signal?.removeEventListener("abort", onAbort);
|
|
4549
5014
|
};
|
|
4550
|
-
const
|
|
5015
|
+
const finalizeResolve = (event) => {
|
|
4551
5016
|
if (settled) {
|
|
4552
5017
|
return;
|
|
4553
5018
|
}
|
|
@@ -4555,8 +5020,17 @@ var ThenvoiLink = class {
|
|
|
4555
5020
|
cleanup();
|
|
4556
5021
|
resolve(event);
|
|
4557
5022
|
};
|
|
5023
|
+
const finalizeReject = (error) => {
|
|
5024
|
+
if (settled) {
|
|
5025
|
+
return;
|
|
5026
|
+
}
|
|
5027
|
+
settled = true;
|
|
5028
|
+
cleanup();
|
|
5029
|
+
reject(error);
|
|
5030
|
+
};
|
|
4558
5031
|
const waiter = {
|
|
4559
|
-
resolve:
|
|
5032
|
+
resolve: finalizeResolve,
|
|
5033
|
+
reject: finalizeReject,
|
|
4560
5034
|
cleanup
|
|
4561
5035
|
};
|
|
4562
5036
|
this.waiters.push(waiter);
|
|
@@ -4568,7 +5042,10 @@ var ThenvoiLink = class {
|
|
|
4568
5042
|
next: async () => {
|
|
4569
5043
|
const value = await this.nextEvent();
|
|
4570
5044
|
if (value === null) {
|
|
4571
|
-
return {
|
|
5045
|
+
return {
|
|
5046
|
+
done: true,
|
|
5047
|
+
value: void 0
|
|
5048
|
+
};
|
|
4572
5049
|
}
|
|
4573
5050
|
return { done: false, value };
|
|
4574
5051
|
}
|
|
@@ -4650,7 +5127,9 @@ var ThenvoiLink = class {
|
|
|
4650
5127
|
}
|
|
4651
5128
|
async listChats(request, requestOptions) {
|
|
4652
5129
|
if (!this.rest.listChats) {
|
|
4653
|
-
throw new UnsupportedFeatureError(
|
|
5130
|
+
throw new UnsupportedFeatureError(
|
|
5131
|
+
"Chat listing is not available in current REST adapter"
|
|
5132
|
+
);
|
|
4654
5133
|
}
|
|
4655
5134
|
return this.rest.listChats(request, requestOptions);
|
|
4656
5135
|
}
|
|
@@ -4827,7 +5306,8 @@ var PlatformRuntime = class {
|
|
|
4827
5306
|
agentId: this._agentId,
|
|
4828
5307
|
apiKey: this._apiKey,
|
|
4829
5308
|
wsUrl: this._wsUrl,
|
|
4830
|
-
restUrl: this._restUrl
|
|
5309
|
+
restUrl: this._restUrl,
|
|
5310
|
+
logger: this.logger
|
|
4831
5311
|
});
|
|
4832
5312
|
}
|
|
4833
5313
|
if (this.configuredIdentity) {
|
|
@@ -5104,16 +5584,15 @@ var RoomPresence = class {
|
|
|
5104
5584
|
}
|
|
5105
5585
|
};
|
|
5106
5586
|
|
|
5107
|
-
// src/runtime/prompts.ts
|
|
5108
|
-
var
|
|
5587
|
+
// src/runtime/prompts/base.ts
|
|
5588
|
+
var ENVIRONMENT_SECTION = `
|
|
5109
5589
|
## Environment
|
|
5110
5590
|
|
|
5111
5591
|
Multi-participant chat. Messages show sender: [Name]: content.
|
|
5112
5592
|
Messages prefixed with [System]: are platform updates (participant changes, contact updates, etc.) \u2014 not messages from users.
|
|
5113
5593
|
Use \`thenvoi_send_message(content, mentions)\` to respond. Plain text output is not delivered.
|
|
5114
|
-
Mentions use handles: @<username> for users, @<username>/<agent-name> for agents
|
|
5115
|
-
|
|
5116
|
-
## CRITICAL: Delegate When You Cannot Help Directly
|
|
5594
|
+
Mentions use handles: @<username> for users, @<username>/<agent-name> for agents.`;
|
|
5595
|
+
var MULTI_AGENT_RULES_SECTION = `## CRITICAL: Delegate When You Cannot Help Directly
|
|
5117
5596
|
|
|
5118
5597
|
You have NO internet access and NO real-time data. When asked about weather, news, stock prices,
|
|
5119
5598
|
or any current information you cannot answer directly:
|
|
@@ -5139,14 +5618,12 @@ Only remove agents if the user explicitly requests it.
|
|
|
5139
5618
|
When someone asks you to get information from another agent:
|
|
5140
5619
|
1. Ask the other agent for the information
|
|
5141
5620
|
2. When you receive the response, IMMEDIATELY relay it back to the ORIGINAL REQUESTER
|
|
5142
|
-
3. Do NOT just thank the helper agent - the requester is waiting for their answer
|
|
5143
|
-
|
|
5144
|
-
## IMPORTANT: Always Share Your Thinking
|
|
5621
|
+
3. Do NOT just thank the helper agent - the requester is waiting for their answer!`;
|
|
5622
|
+
var THINKING_SECTION = `## IMPORTANT: Always Share Your Thinking
|
|
5145
5623
|
|
|
5146
5624
|
You MUST call \`thenvoi_send_event(content, message_type="thought")\` BEFORE every action.
|
|
5147
|
-
This is required so users can see your reasoning process
|
|
5148
|
-
|
|
5149
|
-
## Examples
|
|
5625
|
+
This is required so users can see your reasoning process.`;
|
|
5626
|
+
var EXAMPLES_SECTION = `## Examples
|
|
5150
5627
|
|
|
5151
5628
|
### Simple question - answer directly
|
|
5152
5629
|
[John Doe]: What's 2+2?
|
|
@@ -5179,8 +5656,73 @@ This is required so users can see your reasoning process.
|
|
|
5179
5656
|
|
|
5180
5657
|
[Weather Agent]: London is 8\xB0C and rainy.
|
|
5181
5658
|
-> thenvoi_send_event("Got London weather. Relaying to John Doe.", message_type="thought")
|
|
5182
|
-
-> thenvoi_send_message("London is 8\xB0C and rainy.", mentions=["@john"])
|
|
5183
|
-
|
|
5659
|
+
-> thenvoi_send_message("London is 8\xB0C and rainy.", mentions=["@john"])`;
|
|
5660
|
+
var BASE_INSTRUCTIONS = [
|
|
5661
|
+
ENVIRONMENT_SECTION,
|
|
5662
|
+
MULTI_AGENT_RULES_SECTION,
|
|
5663
|
+
THINKING_SECTION,
|
|
5664
|
+
EXAMPLES_SECTION
|
|
5665
|
+
].join("\n\n") + "\n";
|
|
5666
|
+
|
|
5667
|
+
// src/runtime/prompts/memory.ts
|
|
5668
|
+
var MEMORY_INTRO = `## Memory Tools
|
|
5669
|
+
|
|
5670
|
+
You have access to memory tools for storing and retrieving information
|
|
5671
|
+
across conversations. Use \`thenvoi_store_memory\` to persist important
|
|
5672
|
+
information and \`thenvoi_list_memories\` / \`thenvoi_get_memory\` to recall it.
|
|
5673
|
+
Use \`thenvoi_supersede_memory\` to mark outdated memories and
|
|
5674
|
+
\`thenvoi_archive_memory\` to hide memories that should be preserved.`;
|
|
5675
|
+
function longTermPattern(label, type, segment, scope) {
|
|
5676
|
+
return {
|
|
5677
|
+
label,
|
|
5678
|
+
system: MEMORY_SYSTEM.long_term,
|
|
5679
|
+
type,
|
|
5680
|
+
segment,
|
|
5681
|
+
scope
|
|
5682
|
+
};
|
|
5683
|
+
}
|
|
5684
|
+
var COMMON_MEMORY_PATTERNS = [
|
|
5685
|
+
longTermPattern("Facts learned about a specific agent/entity", MEMORY_TYPE.semantic, MEMORY_SEGMENT.agent, MEMORY_STORE_SCOPE.subject),
|
|
5686
|
+
longTermPattern("Events involving a specific person/agent", MEMORY_TYPE.episodic, MEMORY_SEGMENT.agent, MEMORY_STORE_SCOPE.subject),
|
|
5687
|
+
longTermPattern("A user's preferences or profile info", MEMORY_TYPE.semantic, MEMORY_SEGMENT.user, MEMORY_STORE_SCOPE.subject),
|
|
5688
|
+
longTermPattern("Org-wide knowledge or how to perform a task", MEMORY_TYPE.procedural, MEMORY_SEGMENT.tool, MEMORY_STORE_SCOPE.organization)
|
|
5689
|
+
];
|
|
5690
|
+
function renderMemoryPattern(pattern) {
|
|
5691
|
+
return `- ${pattern.label}: \`system="${pattern.system}"\`, \`type="${pattern.type}"\`, \`segment="${pattern.segment}"\`, \`scope="${pattern.scope}"\``;
|
|
5692
|
+
}
|
|
5693
|
+
var MEMORY_COMMON_PATTERNS = [
|
|
5694
|
+
"Common patterns:",
|
|
5695
|
+
...COMMON_MEMORY_PATTERNS.map(renderMemoryPattern)
|
|
5696
|
+
].join("\n");
|
|
5697
|
+
var MEMORY_SCOPE_GUIDANCE = `Prefer \`scope="${MEMORY_STORE_SCOPE.subject}"\` whenever the memory is about a specific person or agent, so it
|
|
5698
|
+
stays attached to that subject rather than leaking org-wide. Storing with \`scope="${MEMORY_STORE_SCOPE.subject}"\` requires a
|
|
5699
|
+
real \`subject_id\` UUID, so resolve it first via \`thenvoi_lookup_peers\` or the participant list.
|
|
5700
|
+
Reserve \`scope="${MEMORY_STORE_SCOPE.organization}"\` for knowledge that is genuinely shared across the whole organization and
|
|
5701
|
+
is not about any one subject.`;
|
|
5702
|
+
function quoteChoices(values) {
|
|
5703
|
+
return values.map((value) => `\`"${value}"\``).join(" | ");
|
|
5704
|
+
}
|
|
5705
|
+
function memoryTypeLines() {
|
|
5706
|
+
return Object.entries(MEMORY_SYSTEM_TYPES).map(([system, types]) => ` - ${system}: ${quoteChoices(types)}`).join("\n");
|
|
5707
|
+
}
|
|
5708
|
+
function buildMemorySection() {
|
|
5709
|
+
const storeMemoryProps = TOOL_MODELS.thenvoi_store_memory.properties;
|
|
5710
|
+
const systems = storeMemoryProps.system.enum;
|
|
5711
|
+
const segments = storeMemoryProps.segment.enum;
|
|
5712
|
+
const scopes = storeMemoryProps.scope.enum;
|
|
5713
|
+
const fieldRules = `When calling \`thenvoi_store_memory\`, the \`system\`, \`type\`, \`segment\`, and \`scope\` fields
|
|
5714
|
+
must use these exact values (case-sensitive):
|
|
5715
|
+
|
|
5716
|
+
- **system**: ${quoteChoices(systems)}
|
|
5717
|
+
- **type** (must match the chosen system):
|
|
5718
|
+
${memoryTypeLines()}
|
|
5719
|
+
- **segment**: ${quoteChoices(segments)}
|
|
5720
|
+
- **scope**: ${quoteChoices(scopes)}`;
|
|
5721
|
+
return [MEMORY_INTRO, fieldRules, MEMORY_COMMON_PATTERNS, MEMORY_SCOPE_GUIDANCE].join("\n\n");
|
|
5722
|
+
}
|
|
5723
|
+
var MEMORY_SECTION = buildMemorySection();
|
|
5724
|
+
|
|
5725
|
+
// src/runtime/prompts/templates.ts
|
|
5184
5726
|
var TEMPLATES = {
|
|
5185
5727
|
default: `You are {agent_name}, {agent_description}.
|
|
5186
5728
|
|
|
@@ -5199,7 +5741,13 @@ ${customSection}`.trim();
|
|
|
5199
5741
|
}
|
|
5200
5742
|
const template = options?.template ?? "default";
|
|
5201
5743
|
const templateString = TEMPLATES[template] ?? TEMPLATES.default;
|
|
5202
|
-
|
|
5744
|
+
const parts = [
|
|
5745
|
+
templateString.replaceAll("{agent_name}", agentName).replaceAll("{agent_description}", agentDescription).replaceAll("{custom_section}", customSection)
|
|
5746
|
+
];
|
|
5747
|
+
if (options?.capabilities?.memory) {
|
|
5748
|
+
parts.push(MEMORY_SECTION);
|
|
5749
|
+
}
|
|
5750
|
+
return parts.join("\n\n");
|
|
5203
5751
|
}
|
|
5204
5752
|
|
|
5205
5753
|
// src/runtime/participantTracker.ts
|
|
@@ -5336,6 +5884,7 @@ async function runWithGracefulShutdown(agent, options) {
|
|
|
5336
5884
|
HUB_ROOM_SYSTEM_PROMPT,
|
|
5337
5885
|
HistoryProvider,
|
|
5338
5886
|
MCP_TOOL_PREFIX,
|
|
5887
|
+
MEMORY_SECTION,
|
|
5339
5888
|
MEMORY_TOOL_NAMES,
|
|
5340
5889
|
MessageRetryTracker,
|
|
5341
5890
|
ParticipantTracker,
|