@yanlinglabs/winter-agent-sdk 0.0.1 → 0.0.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/index-h1tryj38.js +614 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +231 -0
- package/dist/messaging/adapter.d.ts +119 -0
- package/dist/messaging/addressing.d.ts +13 -0
- package/dist/messaging/attribution.d.ts +43 -0
- package/dist/messaging/idle.d.ts +54 -0
- package/dist/messaging/inbound.d.ts +39 -0
- package/dist/messaging/index.d.ts +15 -0
- package/dist/messaging/index.js +118 -0
- package/dist/messaging/outcomes.d.ts +25 -0
- package/dist/messaging/resolution.d.ts +39 -0
- package/dist/messaging/router.d.ts +90 -0
- package/dist/protocol/messaging.d.ts +111 -0
- package/dist/query.d.ts +91 -0
- package/package.json +9 -5
package/dist/index.js
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import {
|
|
2
|
+
deliveryUncertain2,
|
|
3
|
+
refused2,
|
|
4
|
+
unavailable2
|
|
5
|
+
} from "./index-h1tryj38.js";
|
|
6
|
+
|
|
1
7
|
// src/query.ts
|
|
2
8
|
import { randomUUID } from "node:crypto";
|
|
3
9
|
|
|
@@ -349,6 +355,134 @@ function resolveKeychainServiceForProfile(brand, env, hostSetKeychainService) {
|
|
|
349
355
|
return suffixed.length <= 64 ? suffixed : brand.keychainService;
|
|
350
356
|
}
|
|
351
357
|
|
|
358
|
+
// src/protocol/messaging.ts
|
|
359
|
+
var MESSAGING_CONTROL_SUBTYPES = {
|
|
360
|
+
listReachable: "messaging.list_reachable",
|
|
361
|
+
deliver: "messaging.deliver",
|
|
362
|
+
steerChild: "messaging.steer_child",
|
|
363
|
+
resumeChild: "messaging.resume_child",
|
|
364
|
+
subscribeIdle: "messaging.subscribe_idle",
|
|
365
|
+
senderClass: "messaging.sender_class",
|
|
366
|
+
readNotifications: "messaging.read_notifications",
|
|
367
|
+
idleNotice: "messaging.idle_notice"
|
|
368
|
+
};
|
|
369
|
+
var MESSAGING_HOST_REQUEST_SUBTYPES = [
|
|
370
|
+
MESSAGING_CONTROL_SUBTYPES.listReachable,
|
|
371
|
+
MESSAGING_CONTROL_SUBTYPES.deliver,
|
|
372
|
+
MESSAGING_CONTROL_SUBTYPES.steerChild,
|
|
373
|
+
MESSAGING_CONTROL_SUBTYPES.resumeChild,
|
|
374
|
+
MESSAGING_CONTROL_SUBTYPES.subscribeIdle,
|
|
375
|
+
MESSAGING_CONTROL_SUBTYPES.senderClass,
|
|
376
|
+
MESSAGING_CONTROL_SUBTYPES.readNotifications
|
|
377
|
+
];
|
|
378
|
+
var MESSAGING_RUNTIME_REQUEST_SUBTYPES = [MESSAGING_CONTROL_SUBTYPES.idleNotice];
|
|
379
|
+
var MESSAGING_CONTROL_SUBTYPE_LIST = Object.values(MESSAGING_CONTROL_SUBTYPES);
|
|
380
|
+
function isRecord(v) {
|
|
381
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
382
|
+
}
|
|
383
|
+
var RUNTIME_OBJECT_KINDS = ["session", "agent"];
|
|
384
|
+
var RUNTIME_KINDS = ["claude-agent", "winter-agent"];
|
|
385
|
+
var PERMISSION_CLASS_LABELS = ["prompts", "bypasses", "unknown"];
|
|
386
|
+
var DELIVERY_STATUSES = [
|
|
387
|
+
"delivered",
|
|
388
|
+
"queued",
|
|
389
|
+
"resumed_and_delivered",
|
|
390
|
+
"held",
|
|
391
|
+
"subscribed",
|
|
392
|
+
"delivery_uncertain",
|
|
393
|
+
"refused",
|
|
394
|
+
"ambiguous",
|
|
395
|
+
"not_found",
|
|
396
|
+
"unavailable"
|
|
397
|
+
];
|
|
398
|
+
function isRuntimeAddress(v) {
|
|
399
|
+
if (!isRecord(v))
|
|
400
|
+
return false;
|
|
401
|
+
if (!RUNTIME_OBJECT_KINDS.includes(v.objectKind))
|
|
402
|
+
return false;
|
|
403
|
+
if (!RUNTIME_KINDS.includes(v.runtimeKind))
|
|
404
|
+
return false;
|
|
405
|
+
if (typeof v.winterSessionId !== "string" || v.winterSessionId.length === 0)
|
|
406
|
+
return false;
|
|
407
|
+
if (v.objectKind === "agent" && (typeof v.childId !== "string" || v.childId.length === 0))
|
|
408
|
+
return false;
|
|
409
|
+
return true;
|
|
410
|
+
}
|
|
411
|
+
function isGlobalAgentMessage(v) {
|
|
412
|
+
if (!isRecord(v))
|
|
413
|
+
return false;
|
|
414
|
+
if (typeof v.messageId !== "string" || v.messageId.length === 0)
|
|
415
|
+
return false;
|
|
416
|
+
if (!isRuntimeAddress(v.from) || !isRuntimeAddress(v.to))
|
|
417
|
+
return false;
|
|
418
|
+
if (typeof v.body !== "string")
|
|
419
|
+
return false;
|
|
420
|
+
if (typeof v.notifyWhenIdle !== "boolean")
|
|
421
|
+
return false;
|
|
422
|
+
if (typeof v.hopCount !== "number")
|
|
423
|
+
return false;
|
|
424
|
+
if (!PERMISSION_CLASS_LABELS.includes(v.senderPermissionClass))
|
|
425
|
+
return false;
|
|
426
|
+
return true;
|
|
427
|
+
}
|
|
428
|
+
function isDeliveryOutcome(v) {
|
|
429
|
+
if (!isRecord(v))
|
|
430
|
+
return false;
|
|
431
|
+
if (!DELIVERY_STATUSES.includes(v.status))
|
|
432
|
+
return false;
|
|
433
|
+
if (typeof v.messageId !== "string")
|
|
434
|
+
return false;
|
|
435
|
+
if (v.status === "ambiguous" && !Array.isArray(v.candidates))
|
|
436
|
+
return false;
|
|
437
|
+
if (v.status === "unavailable" && typeof v.retryable !== "boolean")
|
|
438
|
+
return false;
|
|
439
|
+
return true;
|
|
440
|
+
}
|
|
441
|
+
function isListedRuntimeObjectArray(v) {
|
|
442
|
+
return Array.isArray(v) && v.every((row) => isRecord(row) && typeof row.address === "string" && RUNTIME_OBJECT_KINDS.includes(row.objectKind) && isRecord(row.capabilities));
|
|
443
|
+
}
|
|
444
|
+
function isPermissionClassLabel(v) {
|
|
445
|
+
return typeof v === "string" && PERMISSION_CLASS_LABELS.includes(v);
|
|
446
|
+
}
|
|
447
|
+
function isMessagingDeliverRequest(v) {
|
|
448
|
+
return isRecord(v) && isGlobalAgentMessage(v.message);
|
|
449
|
+
}
|
|
450
|
+
function isMessagingChildRequest(v) {
|
|
451
|
+
return isRecord(v) && typeof v.id === "string" && v.id.length > 0 && isGlobalAgentMessage(v.message);
|
|
452
|
+
}
|
|
453
|
+
function isNotificationRecord(v) {
|
|
454
|
+
return isRecord(v) && typeof v.notification_id === "string" && typeof v.origin === "string" && typeof v.queued_at === "string" && typeof v.content === "string";
|
|
455
|
+
}
|
|
456
|
+
function isMessagingNotificationsPage(v) {
|
|
457
|
+
return isRecord(v) && Array.isArray(v.notifications) && v.notifications.every(isNotificationRecord) && typeof v.remaining === "number";
|
|
458
|
+
}
|
|
459
|
+
function isMessagingIdleNoticePayload(v) {
|
|
460
|
+
return isRecord(v) && typeof v.subscriberSessionId === "string" && isNotificationRecord(v.notice);
|
|
461
|
+
}
|
|
462
|
+
function isMessagingReadNotificationsRequest(v) {
|
|
463
|
+
if (!isRecord(v))
|
|
464
|
+
return false;
|
|
465
|
+
if (v.subscriberSessionId !== undefined && typeof v.subscriberSessionId !== "string")
|
|
466
|
+
return false;
|
|
467
|
+
if (v.max !== undefined && (typeof v.max !== "number" || !Number.isFinite(v.max) || v.max < 0))
|
|
468
|
+
return false;
|
|
469
|
+
return true;
|
|
470
|
+
}
|
|
471
|
+
function isMessagingSubscribeIdleRequest(v) {
|
|
472
|
+
if (!isRecord(v))
|
|
473
|
+
return false;
|
|
474
|
+
if (typeof v.id !== "string" || v.id.length === 0)
|
|
475
|
+
return false;
|
|
476
|
+
if (typeof v.messageId !== "string" || v.messageId.length === 0)
|
|
477
|
+
return false;
|
|
478
|
+
if (v.subscriberSessionId !== undefined && typeof v.subscriberSessionId !== "string")
|
|
479
|
+
return false;
|
|
480
|
+
return true;
|
|
481
|
+
}
|
|
482
|
+
function resolveFacetTarget(sessionId, id, parse, buildChild) {
|
|
483
|
+
return parse(id) ?? buildChild(sessionId, id);
|
|
484
|
+
}
|
|
485
|
+
|
|
352
486
|
// src/query.ts
|
|
353
487
|
var DEFAULT_MAX_BUFFER_SIZE = 1024 * 1024;
|
|
354
488
|
var KILL_GRACE_MS = 50;
|
|
@@ -819,6 +953,7 @@ function query(args) {
|
|
|
819
953
|
}
|
|
820
954
|
}
|
|
821
955
|
}
|
|
956
|
+
const idleNoticeHandlers = new Set;
|
|
822
957
|
const gen = iterate();
|
|
823
958
|
gen.interrupt = async () => {
|
|
824
959
|
await sendControlRequest("interrupt", { scope: "turn" });
|
|
@@ -841,6 +976,85 @@ function query(args) {
|
|
|
841
976
|
gen.setPermissionMode = async (mode) => {
|
|
842
977
|
await sendControlRequest("set_permission_mode", mode);
|
|
843
978
|
};
|
|
979
|
+
async function deliveryCall(subtype, payload, messageId) {
|
|
980
|
+
let answer;
|
|
981
|
+
try {
|
|
982
|
+
answer = await sendControlRequest(subtype, payload);
|
|
983
|
+
} catch (err) {
|
|
984
|
+
const code = err instanceof WinterRpcError ? err.code : "";
|
|
985
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
986
|
+
if (code === "invalid_messaging_request")
|
|
987
|
+
return refused2(messageId, message);
|
|
988
|
+
if (code === "messaging_unavailable")
|
|
989
|
+
return unavailable2(messageId, false, message);
|
|
990
|
+
return deliveryUncertain2(messageId, `'${subtype}' failed: ${message}`);
|
|
991
|
+
}
|
|
992
|
+
return isDeliveryOutcome(answer) ? answer : deliveryUncertain2(messageId, `the runtime returned a malformed delivery outcome for '${subtype}'`);
|
|
993
|
+
}
|
|
994
|
+
gen.messaging = {
|
|
995
|
+
async listReachable() {
|
|
996
|
+
const payload = await sendControlRequest(MESSAGING_CONTROL_SUBTYPES.listReachable, undefined).catch(() => {
|
|
997
|
+
return;
|
|
998
|
+
});
|
|
999
|
+
return isListedRuntimeObjectArray(payload) ? payload : [];
|
|
1000
|
+
},
|
|
1001
|
+
deliver(msg) {
|
|
1002
|
+
const request = { message: msg };
|
|
1003
|
+
return deliveryCall(MESSAGING_CONTROL_SUBTYPES.deliver, request, msg.messageId);
|
|
1004
|
+
},
|
|
1005
|
+
steerChild(id, msg) {
|
|
1006
|
+
const request = { id, message: msg };
|
|
1007
|
+
return deliveryCall(MESSAGING_CONTROL_SUBTYPES.steerChild, request, msg.messageId);
|
|
1008
|
+
},
|
|
1009
|
+
resumeChild(id, msg) {
|
|
1010
|
+
const request = { id, message: msg };
|
|
1011
|
+
return deliveryCall(MESSAGING_CONTROL_SUBTYPES.resumeChild, request, msg.messageId);
|
|
1012
|
+
},
|
|
1013
|
+
subscribeIdle(id, opts) {
|
|
1014
|
+
const request = {
|
|
1015
|
+
id,
|
|
1016
|
+
messageId: opts.messageId,
|
|
1017
|
+
...opts.subscriberSessionId !== undefined ? { subscriberSessionId: opts.subscriberSessionId } : {}
|
|
1018
|
+
};
|
|
1019
|
+
return deliveryCall(MESSAGING_CONTROL_SUBTYPES.subscribeIdle, request, opts.messageId);
|
|
1020
|
+
},
|
|
1021
|
+
async senderClass() {
|
|
1022
|
+
const payload = await sendControlRequest(MESSAGING_CONTROL_SUBTYPES.senderClass, undefined).catch(() => {
|
|
1023
|
+
return;
|
|
1024
|
+
});
|
|
1025
|
+
const label = typeof payload === "object" && payload !== null ? payload.senderClass : undefined;
|
|
1026
|
+
return isPermissionClassLabel(label) ? label : "unknown";
|
|
1027
|
+
},
|
|
1028
|
+
async readNotifications(opts) {
|
|
1029
|
+
const request = {
|
|
1030
|
+
...opts?.subscriberSessionId !== undefined ? { subscriberSessionId: opts.subscriberSessionId } : {},
|
|
1031
|
+
...opts?.max !== undefined ? { max: opts.max } : {}
|
|
1032
|
+
};
|
|
1033
|
+
const payload = await sendControlRequest(MESSAGING_CONTROL_SUBTYPES.readNotifications, request).catch(() => {
|
|
1034
|
+
return;
|
|
1035
|
+
});
|
|
1036
|
+
return isMessagingNotificationsPage(payload) ? payload : { notifications: [], remaining: 0 };
|
|
1037
|
+
},
|
|
1038
|
+
onIdleNotice(handler) {
|
|
1039
|
+
idleNoticeHandlers.add(handler);
|
|
1040
|
+
return () => {
|
|
1041
|
+
idleNoticeHandlers.delete(handler);
|
|
1042
|
+
};
|
|
1043
|
+
}
|
|
1044
|
+
};
|
|
1045
|
+
controlRequestHandlers.set(MESSAGING_CONTROL_SUBTYPES.idleNotice, async (payload) => {
|
|
1046
|
+
if (!isMessagingIdleNoticePayload(payload)) {
|
|
1047
|
+
return { ok: false, error: { code: "invalid_idle_notice", message: "messaging.idle_notice requires { subscriberSessionId: string, notice: NotificationRecord }" } };
|
|
1048
|
+
}
|
|
1049
|
+
for (const handler of [...idleNoticeHandlers]) {
|
|
1050
|
+
try {
|
|
1051
|
+
handler(payload);
|
|
1052
|
+
} catch (err) {
|
|
1053
|
+
console.error(`winter: onIdleNotice handler threw for notification ${payload.notice.notification_id}: ${err instanceof Error ? err.message : String(err)} -- the notice is still queued for readNotifications()`);
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
return { ok: true, payload: { delivered: idleNoticeHandlers.size } };
|
|
1057
|
+
});
|
|
844
1058
|
gen.rewindFiles = async (userMessageId, options) => {
|
|
845
1059
|
const payload = await sendControlRequest("rewind_files", { user_message_id: userMessageId, ...options?.dryRun !== undefined ? { dry_run: options.dryRun } : {} });
|
|
846
1060
|
if (typeof payload !== "object" || payload === null || typeof payload.canRewind !== "boolean") {
|
|
@@ -2136,6 +2350,10 @@ export {
|
|
|
2136
2350
|
FIRST_PARTY_ORIGINATORS,
|
|
2137
2351
|
HOOK_EVENTS,
|
|
2138
2352
|
InvalidBrandError,
|
|
2353
|
+
MESSAGING_CONTROL_SUBTYPES,
|
|
2354
|
+
MESSAGING_CONTROL_SUBTYPE_LIST,
|
|
2355
|
+
MESSAGING_HOST_REQUEST_SUBTYPES,
|
|
2356
|
+
MESSAGING_RUNTIME_REQUEST_SUBTYPES,
|
|
2139
2357
|
OVERLAY_NEVER_KEYS,
|
|
2140
2358
|
PROJECT_PERMISSIVE_KEYS,
|
|
2141
2359
|
PROTOCOL_VERSION,
|
|
@@ -2167,6 +2385,18 @@ export {
|
|
|
2167
2385
|
getSessionInfo,
|
|
2168
2386
|
getSessionMessages,
|
|
2169
2387
|
getSubagentMessages,
|
|
2388
|
+
isDeliveryOutcome,
|
|
2389
|
+
isGlobalAgentMessage,
|
|
2390
|
+
isListedRuntimeObjectArray,
|
|
2391
|
+
isMessagingChildRequest,
|
|
2392
|
+
isMessagingDeliverRequest,
|
|
2393
|
+
isMessagingIdleNoticePayload,
|
|
2394
|
+
isMessagingNotificationsPage,
|
|
2395
|
+
isMessagingReadNotificationsRequest,
|
|
2396
|
+
isMessagingSubscribeIdleRequest,
|
|
2397
|
+
isNotificationRecord,
|
|
2398
|
+
isPermissionClassLabel,
|
|
2399
|
+
isRuntimeAddress,
|
|
2170
2400
|
isUnset,
|
|
2171
2401
|
isWinterMcpServerInstance,
|
|
2172
2402
|
listSessions,
|
|
@@ -2177,6 +2407,7 @@ export {
|
|
|
2177
2407
|
query,
|
|
2178
2408
|
renameSession,
|
|
2179
2409
|
resolveBrand,
|
|
2410
|
+
resolveFacetTarget,
|
|
2180
2411
|
resolveKeychainServiceForProfile,
|
|
2181
2412
|
resolveRuntimeExecutable,
|
|
2182
2413
|
resolveSettings,
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import type { PermissionMode } from "../permissions/types.js";
|
|
2
|
+
export type RuntimeKind = "claude-agent" | "winter-agent";
|
|
3
|
+
export type RuntimeObjectKind = "session" | "agent";
|
|
4
|
+
export interface RuntimeAddress {
|
|
5
|
+
objectKind: RuntimeObjectKind;
|
|
6
|
+
runtimeKind: RuntimeKind;
|
|
7
|
+
winterSessionId: string;
|
|
8
|
+
backendSessionId?: string;
|
|
9
|
+
parentWinterSessionId?: string;
|
|
10
|
+
childId?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function serializeRuntimeAddress(addr: RuntimeAddress): string;
|
|
13
|
+
export interface ListedRuntimeObject {
|
|
14
|
+
address: string;
|
|
15
|
+
name?: string;
|
|
16
|
+
objectKind: RuntimeObjectKind;
|
|
17
|
+
runtimeKind: RuntimeKind;
|
|
18
|
+
status: "starting" | "running" | "idle" | "exited" | "unavailable" | "archived";
|
|
19
|
+
mode: string;
|
|
20
|
+
cwd?: string;
|
|
21
|
+
capabilities: {
|
|
22
|
+
message: boolean;
|
|
23
|
+
resume: boolean;
|
|
24
|
+
notifyWhenIdle: boolean;
|
|
25
|
+
reply: boolean;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export type DeliveryOutcome = {
|
|
29
|
+
status: "delivered";
|
|
30
|
+
messageId: string;
|
|
31
|
+
} | {
|
|
32
|
+
status: "queued";
|
|
33
|
+
messageId: string;
|
|
34
|
+
} | {
|
|
35
|
+
status: "resumed_and_delivered";
|
|
36
|
+
messageId: string;
|
|
37
|
+
} | {
|
|
38
|
+
status: "held";
|
|
39
|
+
messageId: string;
|
|
40
|
+
reason: string;
|
|
41
|
+
} | {
|
|
42
|
+
status: "subscribed";
|
|
43
|
+
messageId: string;
|
|
44
|
+
} | {
|
|
45
|
+
status: "delivery_uncertain";
|
|
46
|
+
messageId: string;
|
|
47
|
+
deliveryMayHaveOccurred: true;
|
|
48
|
+
reason: string;
|
|
49
|
+
} | {
|
|
50
|
+
status: "refused";
|
|
51
|
+
messageId: string;
|
|
52
|
+
reason: string;
|
|
53
|
+
} | {
|
|
54
|
+
status: "ambiguous";
|
|
55
|
+
messageId: string;
|
|
56
|
+
candidates: ListedRuntimeObject[];
|
|
57
|
+
} | {
|
|
58
|
+
status: "not_found";
|
|
59
|
+
messageId: string;
|
|
60
|
+
reason: string;
|
|
61
|
+
} | {
|
|
62
|
+
status: "unavailable";
|
|
63
|
+
messageId: string;
|
|
64
|
+
retryable: boolean;
|
|
65
|
+
reason: string;
|
|
66
|
+
};
|
|
67
|
+
export interface GlobalAgentMessage {
|
|
68
|
+
messageId: string;
|
|
69
|
+
from: RuntimeAddress;
|
|
70
|
+
fromGeneration: number;
|
|
71
|
+
to: RuntimeAddress;
|
|
72
|
+
toGeneration: number;
|
|
73
|
+
body: string;
|
|
74
|
+
summary?: string;
|
|
75
|
+
notifyWhenIdle: boolean;
|
|
76
|
+
createdAt: number;
|
|
77
|
+
expiresAt: number;
|
|
78
|
+
hopCount: number;
|
|
79
|
+
originToolCallId?: string;
|
|
80
|
+
senderPermissionClass: "prompts" | "bypasses" | "unknown";
|
|
81
|
+
}
|
|
82
|
+
export type ChildLikeStatus = "running" | "completed" | "stopped" | "failed";
|
|
83
|
+
export interface ChildLikeRecord {
|
|
84
|
+
id: string;
|
|
85
|
+
parentSessionId: string;
|
|
86
|
+
name?: string;
|
|
87
|
+
permission: {
|
|
88
|
+
effectiveMode: PermissionMode;
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
export interface ChildLike {
|
|
92
|
+
readonly record: ChildLikeRecord;
|
|
93
|
+
status(): ChildLikeStatus;
|
|
94
|
+
steer(msg: GlobalAgentMessage): Promise<DeliveryOutcome>;
|
|
95
|
+
resume(msg: GlobalAgentMessage): Promise<DeliveryOutcome>;
|
|
96
|
+
}
|
|
97
|
+
export interface RuntimeMessagingAdapter {
|
|
98
|
+
listReachable(scope: {
|
|
99
|
+
parent?: RuntimeAddress;
|
|
100
|
+
}): Promise<ListedRuntimeObject[]>;
|
|
101
|
+
steerChild(addr: RuntimeAddress, msg: GlobalAgentMessage): Promise<DeliveryOutcome>;
|
|
102
|
+
resumeChild(addr: RuntimeAddress, msg: GlobalAgentMessage): Promise<DeliveryOutcome>;
|
|
103
|
+
deliverToSession(addr: RuntimeAddress, msg: GlobalAgentMessage): Promise<DeliveryOutcome>;
|
|
104
|
+
subscribeIdle(addr: RuntimeAddress, req: {
|
|
105
|
+
messageId: string;
|
|
106
|
+
}): Promise<DeliveryOutcome>;
|
|
107
|
+
senderPermissionClass(addr: RuntimeAddress): Promise<"prompts" | "bypasses" | "unknown">;
|
|
108
|
+
}
|
|
109
|
+
export interface MessagingRouterSeam {
|
|
110
|
+
allocateMessageId(senderSessionId: string, toolUseId: string): string;
|
|
111
|
+
recordOutcome(messageId: string, outcome: DeliveryOutcome): void;
|
|
112
|
+
lookupOutcome(messageId: string): DeliveryOutcome | undefined;
|
|
113
|
+
children(): ChildLike[];
|
|
114
|
+
}
|
|
115
|
+
export interface FakeMessagingRouterSeam extends MessagingRouterSeam {
|
|
116
|
+
readonly outcomes: Map<string, DeliveryOutcome>;
|
|
117
|
+
setChildren(children: ChildLike[]): void;
|
|
118
|
+
}
|
|
119
|
+
export declare function createFakeMessagingRouterSeam(): FakeMessagingRouterSeam;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type RuntimeAddress, type RuntimeKind } from "./adapter.js";
|
|
2
|
+
export declare const REFERENCE_RUNTIME_KIND: RuntimeKind;
|
|
3
|
+
export type ToFieldValidation = {
|
|
4
|
+
ok: true;
|
|
5
|
+
} | {
|
|
6
|
+
ok: false;
|
|
7
|
+
message: string;
|
|
8
|
+
};
|
|
9
|
+
export declare function validateToField(to: unknown): ToFieldValidation;
|
|
10
|
+
export declare function buildSessionAddress(winterSessionId: string): RuntimeAddress;
|
|
11
|
+
export declare function buildChildAddress(parentWinterSessionId: string, childId: string): RuntimeAddress;
|
|
12
|
+
export declare function parseRuntimeAddress(serialized: string): RuntimeAddress | undefined;
|
|
13
|
+
export declare function sameAddress(a: RuntimeAddress, b: RuntimeAddress): boolean;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/** The tag a rendered turn is wrapped in. One literal, so nothing spells it twice. */
|
|
2
|
+
export declare const AGENT_MESSAGE_TAG = "agent-message";
|
|
3
|
+
/**
|
|
4
|
+
* Fix r2 (N2): the escape that makes the attribution frame mean something.
|
|
5
|
+
*
|
|
6
|
+
* THE FINDING. A rendered turn is TEXT in the receiving session's input, and the runtime concatenates
|
|
7
|
+
* sender-chosen text into it. `body` and `summary` are model-authored on the `SendMessage` path
|
|
8
|
+
* (straight off the tool input), so a subagent could close the runtime's frame and open a second one
|
|
9
|
+
* naming an address it does not own with `sender-permission-class="bypasses"` — measured, delivered
|
|
10
|
+
* intact, and syntactically indistinguishable to the receiving model from the real one. The `from`
|
|
11
|
+
* field was never forgeable; the FRAME was, which made the label decorative.
|
|
12
|
+
*
|
|
13
|
+
* WHAT IS ESCAPED, and nothing more: the two sequences that can end or start a frame (`</tag` and
|
|
14
|
+
* `<tag`) and the double quote that can close an attribute value. A real message never contains the
|
|
15
|
+
* first two, and the quote is escaped only inside attribute values, so "a legitimate message arrives
|
|
16
|
+
* altered" costs a bare `"` in a summary and nothing else. The transformation is VISIBLE rather than
|
|
17
|
+
* silent (`<` / `"`), so a receiver reading a message that genuinely discusses this syntax
|
|
18
|
+
* still sees what was written.
|
|
19
|
+
*
|
|
20
|
+
* WHAT IT IS NOT. Lexical escaping makes the count of attributions in a turn honest; it does not make
|
|
21
|
+
* attribution structural. A protocol-level frame kind — where the receiver's DECODER carries the
|
|
22
|
+
* attribution and a body is inert data whatever it contains — is the real fix, and is recorded as a
|
|
23
|
+
* carry. Until then this is what keeps the label from being trivially imitable.
|
|
24
|
+
*/
|
|
25
|
+
export declare function escapeAttributionText(value: string): string;
|
|
26
|
+
/** The same, plus the attribute-value quote — for anything interpolated INSIDE the opening tag. */
|
|
27
|
+
export declare function escapeAttributionAttribute(value: string): string;
|
|
28
|
+
/**
|
|
29
|
+
* Fix r2 (N5): the queue key the FACET files and drains notifications under, built structurally.
|
|
30
|
+
*
|
|
31
|
+
* DELIBERATELY NOT the bare session id. A session's own model drains `notifications.drain(sessionId)`
|
|
32
|
+
* through its `ReadNotifications` tool, and a drain REMOVES — so one key would have whichever side
|
|
33
|
+
* read first silently eat the other's notices.
|
|
34
|
+
*
|
|
35
|
+
* `RESERVED_NOTIFICATION_KEY_PREFIX` is what makes the namespace a rule rather than a coincidence of
|
|
36
|
+
* string concatenation: a session id that already carries the prefix would otherwise collide back
|
|
37
|
+
* into the model's bucket. Product ids are `s_<hex>` so it cannot happen today, and
|
|
38
|
+
* `isReservedNotificationKey` lets a caller assert it instead of assuming it.
|
|
39
|
+
*/
|
|
40
|
+
export declare const RESERVED_NOTIFICATION_KEY_PREFIX = "host:";
|
|
41
|
+
export declare function facetNotificationKey(sessionId: string): string;
|
|
42
|
+
/** True for a key in the facet's reserved namespace — i.e. one the session's own model never drains. */
|
|
43
|
+
export declare function isReservedNotificationKey(key: string): boolean;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { RuntimeObjectKind } from "./adapter.js";
|
|
2
|
+
export declare function isIdleSubscribeSenderAllowed(sender: {
|
|
3
|
+
isChild: boolean;
|
|
4
|
+
}): boolean;
|
|
5
|
+
export declare function isIdleSubscribeTargetAllowed(target: {
|
|
6
|
+
objectKind: RuntimeObjectKind;
|
|
7
|
+
hasReliableIdleSignal: boolean;
|
|
8
|
+
}): boolean;
|
|
9
|
+
export interface NotificationRecord {
|
|
10
|
+
notification_id: string;
|
|
11
|
+
origin: string;
|
|
12
|
+
queued_at: string;
|
|
13
|
+
content: string;
|
|
14
|
+
}
|
|
15
|
+
export interface NotificationQueue {
|
|
16
|
+
push(ownerKey: string, rec: {
|
|
17
|
+
origin: string;
|
|
18
|
+
content: string;
|
|
19
|
+
queuedAtMs: number;
|
|
20
|
+
}): void;
|
|
21
|
+
/**
|
|
22
|
+
* PHASE 7B: observe every push, WITHOUT consuming it. Returns an unsubscribe.
|
|
23
|
+
*
|
|
24
|
+
* The queue is the DURABLE record a host drains; this is the live signal a host can act on
|
|
25
|
+
* immediately. They are deliberately the same notice, correlated by `notification_id`: a listener
|
|
26
|
+
* that never fires (a crashed host, a host that reconnects later) loses nothing, because the entry
|
|
27
|
+
* is still queued for the drain -- which is what makes WS-15 §6.4's restart recovery possible at
|
|
28
|
+
* all. A listener must therefore NOT drain in response; the host acknowledges by draining.
|
|
29
|
+
*
|
|
30
|
+
* OPTIONAL, so a host that supplies its own `NotificationQueue` implementation still satisfies this
|
|
31
|
+
* interface. Its absence degrades to "drain only", never to a dropped notice.
|
|
32
|
+
*/
|
|
33
|
+
subscribe?(listener: (ownerKey: string, rec: NotificationRecord) => void): () => void;
|
|
34
|
+
drain(ownerKey: string, max?: number): {
|
|
35
|
+
notifications: NotificationRecord[];
|
|
36
|
+
remaining: number;
|
|
37
|
+
};
|
|
38
|
+
pendingCount(ownerKey: string): number;
|
|
39
|
+
}
|
|
40
|
+
export declare function createNotificationQueue(): NotificationQueue;
|
|
41
|
+
export interface PendingIdleSubscription {
|
|
42
|
+
messageId: string;
|
|
43
|
+
subscriberKey: string;
|
|
44
|
+
targetKey: string;
|
|
45
|
+
createdAt: number;
|
|
46
|
+
expiresAt: number;
|
|
47
|
+
}
|
|
48
|
+
export interface IdleSubscriptionStore {
|
|
49
|
+
subscribe(sub: Omit<PendingIdleSubscription, "createdAt" | "expiresAt">, now: number): void;
|
|
50
|
+
fireIdle(targetKey: string, now: number, computeReducedStatus: (subscriberKey: string) => boolean, queue: NotificationQueue, originLabel: string): number;
|
|
51
|
+
sweepExpired(now: number): void;
|
|
52
|
+
pendingCount(targetKey: string): number;
|
|
53
|
+
}
|
|
54
|
+
export declare function createIdleSubscriptionStore(): IdleSubscriptionStore;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { PermissionMode } from "../permissions/types.js";
|
|
2
|
+
export type PermissionClassLabel = "prompts" | "bypasses" | "unknown";
|
|
3
|
+
export type CrossSessionInbound = "accept" | "hold" | "refuse";
|
|
4
|
+
export declare function classifyPermissionMode(mode: PermissionMode, opts: {
|
|
5
|
+
bypassAvailable: boolean;
|
|
6
|
+
}): PermissionClassLabel;
|
|
7
|
+
export declare function mapFromModeToPermissionClass(fromMode: "bypass" | "prompting" | undefined): PermissionClassLabel;
|
|
8
|
+
export declare function defaultInboundResult(receiverClass: PermissionClassLabel, senderClass: PermissionClassLabel): "accept" | "hold";
|
|
9
|
+
export interface InboundDecisionParams {
|
|
10
|
+
authenticated: boolean;
|
|
11
|
+
explicitSetting?: CrossSessionInbound;
|
|
12
|
+
receiverClass: PermissionClassLabel;
|
|
13
|
+
senderClass: PermissionClassLabel;
|
|
14
|
+
}
|
|
15
|
+
export declare function resolveInboundDecision(params: InboundDecisionParams): CrossSessionInbound;
|
|
16
|
+
export interface HeldEntry {
|
|
17
|
+
messageId: string;
|
|
18
|
+
reason: string;
|
|
19
|
+
kind: "default" | "explicit";
|
|
20
|
+
heldAt: number;
|
|
21
|
+
expiresAt?: number;
|
|
22
|
+
}
|
|
23
|
+
export interface Mailbox {
|
|
24
|
+
hold(receiverKey: string, entry: HeldEntry): boolean;
|
|
25
|
+
accept(receiverKey: string): boolean;
|
|
26
|
+
releaseAccepted(receiverKey: string, n?: number): void;
|
|
27
|
+
heldCount(receiverKey: string): number;
|
|
28
|
+
acceptedCount(receiverKey: string): number;
|
|
29
|
+
listHeld(receiverKey: string): readonly HeldEntry[];
|
|
30
|
+
takeHeld(receiverKey: string, messageId: string): HeldEntry | undefined;
|
|
31
|
+
reevaluate(receiverKey: string, decide: (entry: HeldEntry) => CrossSessionInbound): Array<{
|
|
32
|
+
entry: HeldEntry;
|
|
33
|
+
next: CrossSessionInbound;
|
|
34
|
+
}>;
|
|
35
|
+
sweepExpired(receiverKey: string, now: number): HeldEntry[];
|
|
36
|
+
}
|
|
37
|
+
export declare function createMailbox(): Mailbox;
|
|
38
|
+
export declare function buildDefaultHoldEntry(messageId: string, reason: string, now: number): HeldEntry;
|
|
39
|
+
export declare function buildExplicitHoldEntry(messageId: string, reason: string, now: number): HeldEntry;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export { serializeRuntimeAddress, createFakeMessagingRouterSeam, } from "./adapter.js";
|
|
2
|
+
export type { RuntimeKind, RuntimeObjectKind, RuntimeAddress, ListedRuntimeObject, DeliveryOutcome, GlobalAgentMessage, RuntimeMessagingAdapter, MessagingRouterSeam, FakeMessagingRouterSeam, ChildLike, ChildLikeRecord, ChildLikeStatus, } from "./adapter.js";
|
|
3
|
+
export { REFERENCE_RUNTIME_KIND, validateToField, buildSessionAddress, buildChildAddress, parseRuntimeAddress, sameAddress, } from "./addressing.js";
|
|
4
|
+
export type { ToFieldValidation } from "./addressing.js";
|
|
5
|
+
export { MAX_GLOBAL_MESSAGE_SIZE, DEFAULT_MESSAGE_TTL_MS, MAX_HOP_COUNT, RAPID_REPEAT_WINDOW_MS, HELD_INBOX_CAP, ACCEPTED_QUEUE_CAP, DEFAULT_HOLD_EXPIRY_MS, NOTIFY_IDLE_EXPIRY_MS, messageExceedsMaxSize, hopCountExceeded, delivered, queued, resumedAndDelivered, held, subscribed, deliveryUncertain, refused, ambiguous, notFound, unavailable, createLoopGuard, } from "./outcomes.js";
|
|
6
|
+
export type { LoopGuard } from "./outcomes.js";
|
|
7
|
+
export { childToListedRuntimeObject, resolveTarget } from "./resolution.js";
|
|
8
|
+
export type { ResolutionInputs, ResolutionResult } from "./resolution.js";
|
|
9
|
+
export { classifyPermissionMode, mapFromModeToPermissionClass, defaultInboundResult, resolveInboundDecision, createMailbox, buildDefaultHoldEntry, buildExplicitHoldEntry, } from "./inbound.js";
|
|
10
|
+
export type { PermissionClassLabel, CrossSessionInbound, InboundDecisionParams, HeldEntry, Mailbox } from "./inbound.js";
|
|
11
|
+
export { isIdleSubscribeSenderAllowed, isIdleSubscribeTargetAllowed, createNotificationQueue, createIdleSubscriptionStore, } from "./idle.js";
|
|
12
|
+
export type { NotificationRecord, NotificationQueue, PendingIdleSubscription, IdleSubscriptionStore } from "./idle.js";
|
|
13
|
+
export { AGENT_MESSAGE_TAG, RESERVED_NOTIFICATION_KEY_PREFIX, escapeAttributionText, escapeAttributionAttribute, facetNotificationKey, isReservedNotificationKey } from "./attribution.js";
|
|
14
|
+
export { MAX_TRACKED_MESSAGE_IDS, rememberBounded, createMessagingRouterSeam, createSubscriberDirectory, callerAddress, sendMessage, listAgents, readNotifications, createMessagingRouter, } from "./router.js";
|
|
15
|
+
export type { MessagingRouterSeamWithRoster, SubscriberDirectory, MessagingRuntimeDeps, CallerContext, SessionCallerContext, SendMessageInput, NotifyOutcome, SendMessageResult, ListAgentsInput, MessagingRouter, } from "./router.js";
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import {
|
|
2
|
+
serializeRuntimeAddress2,
|
|
3
|
+
createFakeMessagingRouterSeam2,
|
|
4
|
+
REFERENCE_RUNTIME_KIND2,
|
|
5
|
+
validateToField2,
|
|
6
|
+
buildSessionAddress2,
|
|
7
|
+
buildChildAddress2,
|
|
8
|
+
parseRuntimeAddress2,
|
|
9
|
+
sameAddress2,
|
|
10
|
+
MAX_GLOBAL_MESSAGE_SIZE2,
|
|
11
|
+
DEFAULT_MESSAGE_TTL_MS2,
|
|
12
|
+
MAX_HOP_COUNT2,
|
|
13
|
+
RAPID_REPEAT_WINDOW_MS2,
|
|
14
|
+
HELD_INBOX_CAP2,
|
|
15
|
+
ACCEPTED_QUEUE_CAP2,
|
|
16
|
+
DEFAULT_HOLD_EXPIRY_MS2,
|
|
17
|
+
NOTIFY_IDLE_EXPIRY_MS2,
|
|
18
|
+
messageExceedsMaxSize2,
|
|
19
|
+
hopCountExceeded2,
|
|
20
|
+
delivered2,
|
|
21
|
+
queued2,
|
|
22
|
+
resumedAndDelivered2,
|
|
23
|
+
held2,
|
|
24
|
+
subscribed2,
|
|
25
|
+
deliveryUncertain2,
|
|
26
|
+
refused2,
|
|
27
|
+
ambiguous2,
|
|
28
|
+
notFound2,
|
|
29
|
+
unavailable2,
|
|
30
|
+
createLoopGuard2,
|
|
31
|
+
childToListedRuntimeObject2,
|
|
32
|
+
resolveTarget2,
|
|
33
|
+
classifyPermissionMode2,
|
|
34
|
+
mapFromModeToPermissionClass2,
|
|
35
|
+
defaultInboundResult2,
|
|
36
|
+
resolveInboundDecision2,
|
|
37
|
+
createMailbox2,
|
|
38
|
+
buildDefaultHoldEntry2,
|
|
39
|
+
buildExplicitHoldEntry2,
|
|
40
|
+
isIdleSubscribeSenderAllowed2,
|
|
41
|
+
isIdleSubscribeTargetAllowed2,
|
|
42
|
+
createNotificationQueue2,
|
|
43
|
+
createIdleSubscriptionStore2,
|
|
44
|
+
AGENT_MESSAGE_TAG2,
|
|
45
|
+
escapeAttributionText2,
|
|
46
|
+
escapeAttributionAttribute2,
|
|
47
|
+
RESERVED_NOTIFICATION_KEY_PREFIX2,
|
|
48
|
+
facetNotificationKey2,
|
|
49
|
+
isReservedNotificationKey2,
|
|
50
|
+
MAX_TRACKED_MESSAGE_IDS2,
|
|
51
|
+
rememberBounded2,
|
|
52
|
+
createMessagingRouterSeam2,
|
|
53
|
+
createSubscriberDirectory2,
|
|
54
|
+
callerAddress2,
|
|
55
|
+
sendMessage2,
|
|
56
|
+
listAgents2,
|
|
57
|
+
readNotifications2,
|
|
58
|
+
createMessagingRouter2
|
|
59
|
+
} from "../index-h1tryj38.js";
|
|
60
|
+
export {
|
|
61
|
+
ACCEPTED_QUEUE_CAP2 as ACCEPTED_QUEUE_CAP,
|
|
62
|
+
AGENT_MESSAGE_TAG2 as AGENT_MESSAGE_TAG,
|
|
63
|
+
DEFAULT_HOLD_EXPIRY_MS2 as DEFAULT_HOLD_EXPIRY_MS,
|
|
64
|
+
DEFAULT_MESSAGE_TTL_MS2 as DEFAULT_MESSAGE_TTL_MS,
|
|
65
|
+
HELD_INBOX_CAP2 as HELD_INBOX_CAP,
|
|
66
|
+
MAX_GLOBAL_MESSAGE_SIZE2 as MAX_GLOBAL_MESSAGE_SIZE,
|
|
67
|
+
MAX_HOP_COUNT2 as MAX_HOP_COUNT,
|
|
68
|
+
MAX_TRACKED_MESSAGE_IDS2 as MAX_TRACKED_MESSAGE_IDS,
|
|
69
|
+
NOTIFY_IDLE_EXPIRY_MS2 as NOTIFY_IDLE_EXPIRY_MS,
|
|
70
|
+
RAPID_REPEAT_WINDOW_MS2 as RAPID_REPEAT_WINDOW_MS,
|
|
71
|
+
REFERENCE_RUNTIME_KIND2 as REFERENCE_RUNTIME_KIND,
|
|
72
|
+
RESERVED_NOTIFICATION_KEY_PREFIX2 as RESERVED_NOTIFICATION_KEY_PREFIX,
|
|
73
|
+
ambiguous2 as ambiguous,
|
|
74
|
+
buildChildAddress2 as buildChildAddress,
|
|
75
|
+
buildDefaultHoldEntry2 as buildDefaultHoldEntry,
|
|
76
|
+
buildExplicitHoldEntry2 as buildExplicitHoldEntry,
|
|
77
|
+
buildSessionAddress2 as buildSessionAddress,
|
|
78
|
+
callerAddress2 as callerAddress,
|
|
79
|
+
childToListedRuntimeObject2 as childToListedRuntimeObject,
|
|
80
|
+
classifyPermissionMode2 as classifyPermissionMode,
|
|
81
|
+
createFakeMessagingRouterSeam2 as createFakeMessagingRouterSeam,
|
|
82
|
+
createIdleSubscriptionStore2 as createIdleSubscriptionStore,
|
|
83
|
+
createLoopGuard2 as createLoopGuard,
|
|
84
|
+
createMailbox2 as createMailbox,
|
|
85
|
+
createMessagingRouter2 as createMessagingRouter,
|
|
86
|
+
createMessagingRouterSeam2 as createMessagingRouterSeam,
|
|
87
|
+
createNotificationQueue2 as createNotificationQueue,
|
|
88
|
+
createSubscriberDirectory2 as createSubscriberDirectory,
|
|
89
|
+
defaultInboundResult2 as defaultInboundResult,
|
|
90
|
+
delivered2 as delivered,
|
|
91
|
+
deliveryUncertain2 as deliveryUncertain,
|
|
92
|
+
escapeAttributionAttribute2 as escapeAttributionAttribute,
|
|
93
|
+
escapeAttributionText2 as escapeAttributionText,
|
|
94
|
+
facetNotificationKey2 as facetNotificationKey,
|
|
95
|
+
held2 as held,
|
|
96
|
+
hopCountExceeded2 as hopCountExceeded,
|
|
97
|
+
isIdleSubscribeSenderAllowed2 as isIdleSubscribeSenderAllowed,
|
|
98
|
+
isIdleSubscribeTargetAllowed2 as isIdleSubscribeTargetAllowed,
|
|
99
|
+
isReservedNotificationKey2 as isReservedNotificationKey,
|
|
100
|
+
listAgents2 as listAgents,
|
|
101
|
+
mapFromModeToPermissionClass2 as mapFromModeToPermissionClass,
|
|
102
|
+
messageExceedsMaxSize2 as messageExceedsMaxSize,
|
|
103
|
+
notFound2 as notFound,
|
|
104
|
+
parseRuntimeAddress2 as parseRuntimeAddress,
|
|
105
|
+
queued2 as queued,
|
|
106
|
+
readNotifications2 as readNotifications,
|
|
107
|
+
refused2 as refused,
|
|
108
|
+
rememberBounded2 as rememberBounded,
|
|
109
|
+
resolveInboundDecision2 as resolveInboundDecision,
|
|
110
|
+
resolveTarget2 as resolveTarget,
|
|
111
|
+
resumedAndDelivered2 as resumedAndDelivered,
|
|
112
|
+
sameAddress2 as sameAddress,
|
|
113
|
+
sendMessage2 as sendMessage,
|
|
114
|
+
serializeRuntimeAddress2 as serializeRuntimeAddress,
|
|
115
|
+
subscribed2 as subscribed,
|
|
116
|
+
unavailable2 as unavailable,
|
|
117
|
+
validateToField2 as validateToField
|
|
118
|
+
};
|