@animalabs/agent-framework 0.23.1 → 0.23.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/framework.d.ts +9 -0
- package/dist/src/framework.d.ts.map +1 -1
- package/dist/src/framework.js +55 -7
- package/dist/src/framework.js.map +1 -1
- package/package.json +1 -1
- package/src/framework.ts +58 -7
package/package.json
CHANGED
package/src/framework.ts
CHANGED
|
@@ -282,6 +282,28 @@ const silenceCauseOf = (calls: Array<{ name: string; input?: unknown }>): 'send'
|
|
|
282
282
|
return calls.some(isSilencingCall) ? 'send' : null;
|
|
283
283
|
};
|
|
284
284
|
|
|
285
|
+
/**
|
|
286
|
+
* The keys of a stored message's metadata that only the host writes and that
|
|
287
|
+
* some reader takes on its own as what the message is: `system` and `kind`
|
|
288
|
+
* make it a host notice of that kind, `draftOwner` and `draftIds` one that
|
|
289
|
+
* names those drafts, `tuneOut` a message a tune-out holds from the
|
|
290
|
+
* residents, `coalescingSubject` (beside the occurrence's `eventId`) the
|
|
291
|
+
* delivery of a coalesced occurrence, `deferredWriteId` the landed copy of a
|
|
292
|
+
* deferred write, `external` a module's own row for an outside message, and
|
|
293
|
+
* `openaiResponsesItems` membrane's mark of an imported Responses history. A
|
|
294
|
+
* server's metadata, a channel message's `metadata` or a push event's
|
|
295
|
+
* `origin`, is stored without them, and the host writes its own after it:
|
|
296
|
+
* MCPL SPEC §16.6 makes metadata the producer's untrusted claims, which a
|
|
297
|
+
* host may disbelieve. Keys a server writes by protocol, such as `tags` and
|
|
298
|
+
* `mentioned`, stay. So do the keys a reader takes only beside one of these:
|
|
299
|
+
* a failed reply's `reason` and `detail` beside its `kind`, and the Discord
|
|
300
|
+
* module's `discordTextFirst` on a row it found by `external`.
|
|
301
|
+
*/
|
|
302
|
+
const HOST_METADATA_KEYS = [
|
|
303
|
+
'system', 'kind', 'draftOwner', 'draftIds', 'tuneOut', 'coalescingSubject', 'deferredWriteId',
|
|
304
|
+
'external', 'openaiResponsesItems',
|
|
305
|
+
] as const;
|
|
306
|
+
|
|
285
307
|
/**
|
|
286
308
|
* True when an injected message is real conversational input — something the
|
|
287
309
|
* agent might actually be replying to — rather than ambient machinery.
|
|
@@ -10852,9 +10874,9 @@ export class AgentFramework {
|
|
|
10852
10874
|
// turn ends. The window stores them here, right after the
|
|
10853
10875
|
// tool_result message, which is exactly where the membrane appends
|
|
10854
10876
|
// them in the live conversation — same participant, same content
|
|
10855
|
-
// blocks,
|
|
10856
|
-
// verbatim, so the next turn's compiled prefix
|
|
10857
|
-
// live request (prompt-cache safe).
|
|
10877
|
+
// blocks, and neither carries the row's metadata — and compile()
|
|
10878
|
+
// emits recent messages verbatim, so the next turn's compiled prefix
|
|
10879
|
+
// byte-matches the live request (prompt-cache safe).
|
|
10858
10880
|
//
|
|
10859
10881
|
// The queue is drained ONLY at the target agent's own boundary:
|
|
10860
10882
|
// draining at another agent's boundary would store the messages
|
|
@@ -11109,10 +11131,14 @@ export class AgentFramework {
|
|
|
11109
11131
|
// Streaming path: convert results and resume the stream.
|
|
11110
11132
|
// Mid-turn messages collected above ride along as injected user
|
|
11111
11133
|
// messages (membrane ≥0.5.72) — appended after the tool_result
|
|
11112
|
-
// envelope so the next round of THIS turn hears them.
|
|
11134
|
+
// envelope so the next round of THIS turn hears them. Each goes
|
|
11135
|
+
// as its participant and content alone: a stored row's metadata
|
|
11136
|
+
// is the host's record, not input for membrane.
|
|
11113
11137
|
currentState.stream.provideToolResults(
|
|
11114
11138
|
agent.toolResultGuard.submissionResults(membraneResults),
|
|
11115
|
-
midTurnInjections.length > 0
|
|
11139
|
+
midTurnInjections.length > 0
|
|
11140
|
+
? { injectedMessages: midTurnInjections.map(({ participant, content }) => ({ participant, content })) }
|
|
11141
|
+
: undefined,
|
|
11116
11142
|
);
|
|
11117
11143
|
// RFC-006 §3.3: consumption is determined at assembly, and this
|
|
11118
11144
|
// is assembly too when the stream carries the injected messages
|
|
@@ -11313,6 +11339,31 @@ export class AgentFramework {
|
|
|
11313
11339
|
// Built-in MCPL event → context message conversion
|
|
11314
11340
|
// ==========================================================================
|
|
11315
11341
|
|
|
11342
|
+
/** The servers and keys whose drop withoutHostKeys has logged, each as
|
|
11343
|
+
* `${serverId}\u0000${key}`. */
|
|
11344
|
+
private readonly hostKeysDropped = new Set<string>();
|
|
11345
|
+
|
|
11346
|
+
/**
|
|
11347
|
+
* A server's metadata as it is stored: a copy without HOST_METADATA_KEYS.
|
|
11348
|
+
* A server may use one of those names for something of its own, so the
|
|
11349
|
+
* first drop of each key from each server is logged.
|
|
11350
|
+
*/
|
|
11351
|
+
private withoutHostKeys(serverId: string, given: Record<string, unknown> | undefined): Record<string, unknown> {
|
|
11352
|
+
const kept: Record<string, unknown> = { ...given };
|
|
11353
|
+
for (const key of HOST_METADATA_KEYS) {
|
|
11354
|
+
if (!Object.hasOwn(kept, key)) continue;
|
|
11355
|
+
delete kept[key];
|
|
11356
|
+
const logged = `${serverId}\u0000${key}`;
|
|
11357
|
+
if (this.hostKeysDropped.has(logged)) continue;
|
|
11358
|
+
this.hostKeysDropped.add(logged);
|
|
11359
|
+
console.error(
|
|
11360
|
+
`[mcpl] ${serverId}: dropped "${key}" from a message, since only the host writes that key ` +
|
|
11361
|
+
`(logged once for each server and key)`,
|
|
11362
|
+
);
|
|
11363
|
+
}
|
|
11364
|
+
return kept;
|
|
11365
|
+
}
|
|
11366
|
+
|
|
11316
11367
|
/**
|
|
11317
11368
|
* Convert an incoming MCPL channel message to a context message.
|
|
11318
11369
|
* This replaces the old MCPLModule.onProcess() message conversion.
|
|
@@ -11349,7 +11400,7 @@ export class AgentFramework {
|
|
|
11349
11400
|
return undefined;
|
|
11350
11401
|
}
|
|
11351
11402
|
const metadata: Record<string, unknown> = {
|
|
11352
|
-
...event.metadata,
|
|
11403
|
+
...this.withoutHostKeys(event.serverId, event.metadata),
|
|
11353
11404
|
...(event.eventId ? { eventId: event.eventId } : {}),
|
|
11354
11405
|
...(event.coalescingSubject ? { coalescingSubject: event.coalescingSubject } : {}),
|
|
11355
11406
|
channelId: event.channelId,
|
|
@@ -12810,7 +12861,7 @@ export class AgentFramework {
|
|
|
12810
12861
|
}
|
|
12811
12862
|
|
|
12812
12863
|
const metadata: Record<string, unknown> = {
|
|
12813
|
-
...event.origin,
|
|
12864
|
+
...this.withoutHostKeys(event.serverId, event.origin),
|
|
12814
12865
|
serverId: event.serverId,
|
|
12815
12866
|
featureSet: event.featureSet,
|
|
12816
12867
|
eventId: event.eventId,
|