@axiom-lattice/protocols 4.11.0 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +10 -10
- package/CHANGELOG.md +83 -0
- package/dist/index.d.mts +431 -44
- package/dist/index.d.ts +431 -44
- package/dist/index.js +156 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +142 -5
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/AgentInterruptProtocol.ts +15 -0
- package/src/AgentLatticeProtocol.ts +0 -49
- package/src/AgentWebAppRuntimeProtocol.ts +2 -0
- package/src/ChannelAdapterProtocol.ts +10 -0
- package/src/ChannelReplyJobProtocol.ts +184 -0
- package/src/CheckpointStorageProtocol.ts +98 -0
- package/src/MessageProtocol.ts +8 -0
- package/src/RunCancelProtocol.ts +76 -0
- package/src/StoreProtocol.ts +181 -0
- package/src/ThreadStoreProtocol.ts +24 -0
- package/src/__tests__/RunCancelProtocol.test.ts +148 -0
- package/src/__tests__/agent-web-app-types.test.ts +4 -0
- package/src/index.ts +5 -0
|
@@ -38,6 +38,13 @@ export interface Thread {
|
|
|
38
38
|
* Thread last update timestamp
|
|
39
39
|
*/
|
|
40
40
|
updatedAt: Date;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Optional expiry timestamp used by the thread TTL sweeper.
|
|
44
|
+
*
|
|
45
|
+
* @remarks Absent means the thread never expires.
|
|
46
|
+
*/
|
|
47
|
+
expiresAt?: Date;
|
|
41
48
|
}
|
|
42
49
|
|
|
43
50
|
/**
|
|
@@ -48,6 +55,14 @@ export interface CreateThreadRequest {
|
|
|
48
55
|
* Thread metadata
|
|
49
56
|
*/
|
|
50
57
|
metadata?: Record<string, any>;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Optional thread expiry timestamp.
|
|
61
|
+
*
|
|
62
|
+
* @remarks Routes compute this from `ttlSeconds`/`expiresAt`; the store only
|
|
63
|
+
* persists it.
|
|
64
|
+
*/
|
|
65
|
+
expiresAt?: Date;
|
|
51
66
|
}
|
|
52
67
|
|
|
53
68
|
/**
|
|
@@ -123,4 +138,13 @@ export interface ThreadStore {
|
|
|
123
138
|
* @returns true if thread exists, false otherwise
|
|
124
139
|
*/
|
|
125
140
|
hasThread(tenantId: string, threadId: string): Promise<boolean>;
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* List expired threads across all tenants.
|
|
144
|
+
*
|
|
145
|
+
* @param now Current time; threads with `expiresAt <= now` are returned.
|
|
146
|
+
* @param limit Maximum number of threads to return.
|
|
147
|
+
* @returns Expired threads ordered by `expiresAt` ascending.
|
|
148
|
+
*/
|
|
149
|
+
listExpiredThreads(now: Date, limit: number): Promise<Thread[]>;
|
|
126
150
|
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import {
|
|
2
|
+
a2aEventCursorSchema,
|
|
3
|
+
interruptAnswerKeySchema,
|
|
4
|
+
runCancelSignalSchema,
|
|
5
|
+
} from "../RunCancelProtocol";
|
|
6
|
+
import type {
|
|
7
|
+
A2AEventCursor,
|
|
8
|
+
InterruptAnswerKey,
|
|
9
|
+
RunCancelSignal,
|
|
10
|
+
} from "../RunCancelProtocol";
|
|
11
|
+
import {
|
|
12
|
+
a2aEventCursorSchema as a2aEventCursorSchemaFromIndex,
|
|
13
|
+
interruptAnswerKeySchema as interruptAnswerKeySchemaFromIndex,
|
|
14
|
+
runCancelSignalSchema as runCancelSignalSchemaFromIndex,
|
|
15
|
+
} from "../index";
|
|
16
|
+
|
|
17
|
+
const MAX_FIELD_LENGTH = 64 * 1024;
|
|
18
|
+
|
|
19
|
+
const validCancelSignal: RunCancelSignal = {
|
|
20
|
+
commandId: "command-1",
|
|
21
|
+
tenantId: "tenant-1",
|
|
22
|
+
assistantId: "assistant-1",
|
|
23
|
+
threadId: "thread-1",
|
|
24
|
+
runId: "run-1",
|
|
25
|
+
reason: "abort",
|
|
26
|
+
createdAt: "2026-10-20T00:00:00.000Z",
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const validInterruptAnswerKey: InterruptAnswerKey = {
|
|
30
|
+
tenantId: "tenant-1",
|
|
31
|
+
assistantId: "assistant-1",
|
|
32
|
+
threadId: "thread-1",
|
|
33
|
+
interruptId: "interrupt-1",
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const validA2AEventCursor: A2AEventCursor = {
|
|
37
|
+
taskId: "task-1",
|
|
38
|
+
lastEventId: "event-1",
|
|
39
|
+
updatedAt: "2026-10-20T00:00:00.000Z",
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
describe("runCancelSignalSchema", () => {
|
|
43
|
+
it("round-trips a valid cancellation signal", () => {
|
|
44
|
+
expect(runCancelSignalSchema.parse(validCancelSignal)).toEqual(validCancelSignal);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("accepts every supported reason", () => {
|
|
48
|
+
for (const reason of ["abort", "a2a.cancel", "shutdown"] as const) {
|
|
49
|
+
expect(runCancelSignalSchema.parse({ ...validCancelSignal, reason }).reason).toBe(reason);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it.each(["commandId", "tenantId", "assistantId", "threadId", "runId", "createdAt"] as const)(
|
|
54
|
+
"rejects a signal missing %s",
|
|
55
|
+
(field) => {
|
|
56
|
+
const invalid: Record<string, unknown> = { ...validCancelSignal };
|
|
57
|
+
delete invalid[field];
|
|
58
|
+
|
|
59
|
+
expect(runCancelSignalSchema.safeParse(invalid).success).toBe(false);
|
|
60
|
+
},
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
it.each(["commandId", "tenantId", "threadId", "runId"] as const)(
|
|
64
|
+
"rejects an empty %s",
|
|
65
|
+
(field) => {
|
|
66
|
+
expect(runCancelSignalSchema.safeParse({ ...validCancelSignal, [field]: "" }).success).toBe(false);
|
|
67
|
+
},
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
it("rejects an unknown reason", () => {
|
|
71
|
+
expect(runCancelSignalSchema.safeParse({ ...validCancelSignal, reason: "restart" }).success).toBe(false);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("rejects an oversized field", () => {
|
|
75
|
+
const oversized = "x".repeat(MAX_FIELD_LENGTH + 1);
|
|
76
|
+
|
|
77
|
+
expect(runCancelSignalSchema.safeParse({ ...validCancelSignal, runId: oversized }).success).toBe(false);
|
|
78
|
+
expect(runCancelSignalSchema.safeParse({ ...validCancelSignal, createdAt: oversized }).success).toBe(false);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("rejects unknown keys", () => {
|
|
82
|
+
expect(runCancelSignalSchema.safeParse({ ...validCancelSignal, extra: true }).success).toBe(false);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
describe("interruptAnswerKeySchema", () => {
|
|
87
|
+
it("round-trips a valid interrupt answer key", () => {
|
|
88
|
+
expect(interruptAnswerKeySchema.parse(validInterruptAnswerKey)).toEqual(validInterruptAnswerKey);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it.each(["tenantId", "assistantId", "threadId", "interruptId"] as const)(
|
|
92
|
+
"rejects a key missing %s",
|
|
93
|
+
(field) => {
|
|
94
|
+
const invalid: Record<string, unknown> = { ...validInterruptAnswerKey };
|
|
95
|
+
delete invalid[field];
|
|
96
|
+
|
|
97
|
+
expect(interruptAnswerKeySchema.safeParse(invalid).success).toBe(false);
|
|
98
|
+
},
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
it("rejects an oversized field", () => {
|
|
102
|
+
const oversized = "x".repeat(MAX_FIELD_LENGTH + 1);
|
|
103
|
+
|
|
104
|
+
expect(interruptAnswerKeySchema.safeParse({ ...validInterruptAnswerKey, interruptId: oversized }).success)
|
|
105
|
+
.toBe(false);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it("rejects unknown keys", () => {
|
|
109
|
+
expect(interruptAnswerKeySchema.safeParse({ ...validInterruptAnswerKey, runId: "run-1" }).success)
|
|
110
|
+
.toBe(false);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
describe("a2aEventCursorSchema", () => {
|
|
115
|
+
it("round-trips a valid A2A event cursor", () => {
|
|
116
|
+
expect(a2aEventCursorSchema.parse(validA2AEventCursor)).toEqual(validA2AEventCursor);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it.each(["taskId", "lastEventId", "updatedAt"] as const)(
|
|
120
|
+
"rejects a cursor missing %s",
|
|
121
|
+
(field) => {
|
|
122
|
+
const invalid: Record<string, unknown> = { ...validA2AEventCursor };
|
|
123
|
+
delete invalid[field];
|
|
124
|
+
|
|
125
|
+
expect(a2aEventCursorSchema.safeParse(invalid).success).toBe(false);
|
|
126
|
+
},
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
it("rejects an oversized field", () => {
|
|
130
|
+
const oversized = "x".repeat(MAX_FIELD_LENGTH + 1);
|
|
131
|
+
|
|
132
|
+
expect(a2aEventCursorSchema.safeParse({ ...validA2AEventCursor, lastEventId: oversized }).success)
|
|
133
|
+
.toBe(false);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it("rejects unknown keys", () => {
|
|
137
|
+
expect(a2aEventCursorSchema.safeParse({ ...validA2AEventCursor, tenantId: "tenant-1" }).success)
|
|
138
|
+
.toBe(false);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
describe("package exports", () => {
|
|
143
|
+
it("exposes the contracts from the package entry point", () => {
|
|
144
|
+
expect(runCancelSignalSchemaFromIndex).toBe(runCancelSignalSchema);
|
|
145
|
+
expect(interruptAnswerKeySchemaFromIndex).toBe(interruptAnswerKeySchema);
|
|
146
|
+
expect(a2aEventCursorSchemaFromIndex).toBe(a2aEventCursorSchema);
|
|
147
|
+
});
|
|
148
|
+
});
|
|
@@ -140,6 +140,8 @@ const errorCodes = [
|
|
|
140
140
|
"THREAD_NOT_FOUND",
|
|
141
141
|
"STREAM_CONFLICT",
|
|
142
142
|
"STREAM_FAILED",
|
|
143
|
+
"RUN_CANCEL_UNAVAILABLE",
|
|
144
|
+
"RUN_CANCEL_STORE_UNAVAILABLE",
|
|
143
145
|
"INVALID_REQUEST",
|
|
144
146
|
"INTERNAL_ERROR",
|
|
145
147
|
] as const satisfies readonly AgentWebAppErrorCode[];
|
|
@@ -309,6 +311,8 @@ describe("Agent Web App protocol types", () => {
|
|
|
309
311
|
"THREAD_NOT_FOUND",
|
|
310
312
|
"STREAM_CONFLICT",
|
|
311
313
|
"STREAM_FAILED",
|
|
314
|
+
"RUN_CANCEL_UNAVAILABLE",
|
|
315
|
+
"RUN_CANCEL_STORE_UNAVAILABLE",
|
|
312
316
|
"INVALID_REQUEST",
|
|
313
317
|
"INTERNAL_ERROR",
|
|
314
318
|
]);
|
package/src/index.ts
CHANGED
|
@@ -17,6 +17,7 @@ export * from "./STTModelLatticeProtocol";
|
|
|
17
17
|
export * from "./VectorStoreLatticeProtocol";
|
|
18
18
|
export * from "./LoggerLatticeProtocol";
|
|
19
19
|
export * from "./MessageProtocol";
|
|
20
|
+
export * from "./AgentInterruptProtocol";
|
|
20
21
|
export * from "./ThreadStoreProtocol";
|
|
21
22
|
export * from "./AssistantStoreProtocol";
|
|
22
23
|
export * from "./SkillLatticeProtocol";
|
|
@@ -62,6 +63,9 @@ export * from "./UserPushSubscriptionStoreProtocol";
|
|
|
62
63
|
export * from "./PluginDeploymentStoreProtocol";
|
|
63
64
|
export * from "./LeaseStoreProtocol";
|
|
64
65
|
export * from "./OutboxStoreProtocol";
|
|
66
|
+
export * from "./CheckpointStorageProtocol";
|
|
67
|
+
export * from "./StoreProtocol";
|
|
68
|
+
export * from "./ChannelReplyJobProtocol";
|
|
65
69
|
export * from "./ExactDataSnapshot";
|
|
66
70
|
export * from "./ProjectRoomRealtimeProtocol";
|
|
67
71
|
|
|
@@ -98,6 +102,7 @@ export * from "./SandboxPluginProtocol";
|
|
|
98
102
|
export * from "./types";
|
|
99
103
|
export * from "./TrustedRunContextProtocol";
|
|
100
104
|
export * from "./RunScope";
|
|
105
|
+
export * from "./RunCancelProtocol";
|
|
101
106
|
export * from "./AgentAffinity";
|
|
102
107
|
export * from "./OpenProtocol";
|
|
103
108
|
export * from "./McpUiProtocol";
|