stitchkit 0.56.5 → 0.58.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/dist/agent-runtime/compaction.d.ts +3 -0
- package/dist/agent-runtime/compaction.d.ts.map +1 -1
- package/dist/agent-runtime/events.d.ts +693 -0
- package/dist/agent-runtime/events.d.ts.map +1 -1
- package/dist/agent-runtime/history.d.ts +13 -0
- package/dist/agent-runtime/history.d.ts.map +1 -1
- package/dist/agent-runtime/managed-tools.d.ts +1 -0
- package/dist/agent-runtime/managed-tools.d.ts.map +1 -1
- package/dist/agent-runtime/models.d.ts +39 -3
- package/dist/agent-runtime/models.d.ts.map +1 -1
- package/dist/agent-runtime/observability.d.ts +3 -0
- package/dist/agent-runtime/observability.d.ts.map +1 -1
- package/dist/agent-runtime/prompt.d.ts +21 -0
- package/dist/agent-runtime/prompt.d.ts.map +1 -1
- package/dist/agent-runtime/runtime.d.ts +43 -4
- package/dist/agent-runtime/runtime.d.ts.map +1 -1
- package/dist/agent-runtime/schemas.d.ts +75 -0
- package/dist/agent-runtime/schemas.d.ts.map +1 -1
- package/dist/agent-runtime/store-driver.d.ts +409 -0
- package/dist/agent-runtime/store-driver.d.ts.map +1 -0
- package/dist/agent-runtime/store.d.ts +169 -2
- package/dist/agent-runtime/store.d.ts.map +1 -1
- package/dist/agent-runtime/testing.d.ts +10 -1
- package/dist/agent-runtime/testing.d.ts.map +1 -1
- package/dist/agent-runtime.d.ts +7 -6
- package/dist/agent-runtime.d.ts.map +1 -1
- package/dist/agent-runtime.js +1157 -511
- package/dist/index-vtjgx3vv.js +161 -0
- package/dist/server/error-hook.d.ts +8 -1
- package/dist/server/error-hook.d.ts.map +1 -1
- package/dist/server/index.js +4 -2
- package/dist/testing/agent-store-conformance.d.ts +7 -0
- package/dist/testing/agent-store-conformance.d.ts.map +1 -0
- package/dist/testing.d.ts +2 -0
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +331 -0
- package/llms-full.txt +201 -28
- package/package.json +1 -1
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
// src/agent-runtime/schemas.ts
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
var AgentRecordIdSchema = z.string().min(1);
|
|
4
|
+
var AgentRecordVersionSchema = z.int().nonnegative();
|
|
5
|
+
var AgentTimestampSchema = z.iso.datetime({ offset: true });
|
|
6
|
+
var AgentJsonObjectSchema = z.record(z.string(), z.json());
|
|
7
|
+
var AgentProviderEnvelopeSchema = z.object({
|
|
8
|
+
schemaVersion: z.int().positive(),
|
|
9
|
+
provider: z.string().min(1),
|
|
10
|
+
data: AgentJsonObjectSchema
|
|
11
|
+
});
|
|
12
|
+
var AgentTextPartSchema = z.object({
|
|
13
|
+
type: z.literal("text"),
|
|
14
|
+
text: z.string()
|
|
15
|
+
});
|
|
16
|
+
var AgentReasoningPartSchema = z.object({
|
|
17
|
+
type: z.literal("reasoning"),
|
|
18
|
+
text: z.string(),
|
|
19
|
+
provider: AgentProviderEnvelopeSchema.optional()
|
|
20
|
+
});
|
|
21
|
+
var AgentFilePartSchema = z.object({
|
|
22
|
+
type: z.literal("file"),
|
|
23
|
+
mediaType: z.string().min(1),
|
|
24
|
+
reference: z.string().min(1),
|
|
25
|
+
filename: z.string().min(1).optional()
|
|
26
|
+
});
|
|
27
|
+
var AgentSourcePartSchema = z.object({
|
|
28
|
+
type: z.literal("source"),
|
|
29
|
+
sourceId: z.string().min(1),
|
|
30
|
+
url: z.url().optional(),
|
|
31
|
+
title: z.string().optional()
|
|
32
|
+
});
|
|
33
|
+
var AgentToolCallPartSchema = z.object({
|
|
34
|
+
type: z.literal("tool-call"),
|
|
35
|
+
callId: z.string().min(1),
|
|
36
|
+
toolName: z.string().min(1),
|
|
37
|
+
input: z.json(),
|
|
38
|
+
provider: AgentProviderEnvelopeSchema.optional()
|
|
39
|
+
});
|
|
40
|
+
var AgentToolResultPartSchema = z.object({
|
|
41
|
+
type: z.literal("tool-result"),
|
|
42
|
+
callId: z.string().min(1),
|
|
43
|
+
toolName: z.string().min(1),
|
|
44
|
+
outcome: z.enum(["success", "error", "interrupted"]),
|
|
45
|
+
output: z.json().optional()
|
|
46
|
+
});
|
|
47
|
+
var AgentOpaquePartSchema = z.object({
|
|
48
|
+
type: z.literal("provider"),
|
|
49
|
+
envelope: AgentProviderEnvelopeSchema
|
|
50
|
+
});
|
|
51
|
+
var AgentControlPartSchema = z.object({
|
|
52
|
+
type: z.literal("control"),
|
|
53
|
+
reason: z.enum(["run-interrupted", "stale-run"])
|
|
54
|
+
});
|
|
55
|
+
var AgentMessagePartSchema = z.discriminatedUnion("type", [
|
|
56
|
+
AgentTextPartSchema,
|
|
57
|
+
AgentReasoningPartSchema,
|
|
58
|
+
AgentFilePartSchema,
|
|
59
|
+
AgentSourcePartSchema,
|
|
60
|
+
AgentToolCallPartSchema,
|
|
61
|
+
AgentToolResultPartSchema,
|
|
62
|
+
AgentOpaquePartSchema,
|
|
63
|
+
AgentControlPartSchema
|
|
64
|
+
]);
|
|
65
|
+
var AgentMessageRoleSchema = z.enum(["user", "assistant", "system", "summary"]);
|
|
66
|
+
var AgentMessageStatusSchema = z.enum([
|
|
67
|
+
"committed",
|
|
68
|
+
"streaming",
|
|
69
|
+
"completed",
|
|
70
|
+
"interrupted",
|
|
71
|
+
"failed"
|
|
72
|
+
]);
|
|
73
|
+
var AgentMessageSchema = z.object({
|
|
74
|
+
schemaVersion: z.literal(1),
|
|
75
|
+
id: AgentRecordIdSchema,
|
|
76
|
+
conversationId: AgentRecordIdSchema,
|
|
77
|
+
runId: AgentRecordIdSchema.optional(),
|
|
78
|
+
role: AgentMessageRoleSchema,
|
|
79
|
+
status: AgentMessageStatusSchema,
|
|
80
|
+
parts: z.array(AgentMessagePartSchema),
|
|
81
|
+
metadata: AgentJsonObjectSchema.optional(),
|
|
82
|
+
createdAt: AgentTimestampSchema,
|
|
83
|
+
updatedAt: AgentTimestampSchema
|
|
84
|
+
});
|
|
85
|
+
var AgentAssistantPlaceholderSchema = z.object({
|
|
86
|
+
schemaVersion: z.literal(1),
|
|
87
|
+
id: AgentRecordIdSchema,
|
|
88
|
+
conversationId: AgentRecordIdSchema,
|
|
89
|
+
runId: AgentRecordIdSchema,
|
|
90
|
+
status: z.literal("pending"),
|
|
91
|
+
createdAt: AgentTimestampSchema,
|
|
92
|
+
updatedAt: AgentTimestampSchema
|
|
93
|
+
});
|
|
94
|
+
var AgentRunStateSchema = z.enum([
|
|
95
|
+
"queued",
|
|
96
|
+
"running",
|
|
97
|
+
"interrupt_requested",
|
|
98
|
+
"completed",
|
|
99
|
+
"interrupted",
|
|
100
|
+
"failed",
|
|
101
|
+
"cancelled",
|
|
102
|
+
"abandoned"
|
|
103
|
+
]);
|
|
104
|
+
var AgentTerminalReasonSchema = z.enum([
|
|
105
|
+
"success",
|
|
106
|
+
"policy_stop",
|
|
107
|
+
"interrupted",
|
|
108
|
+
"cancelled",
|
|
109
|
+
"timeout",
|
|
110
|
+
"shutdown",
|
|
111
|
+
"provider_failure",
|
|
112
|
+
"tool_failure",
|
|
113
|
+
"abandoned"
|
|
114
|
+
]);
|
|
115
|
+
var AgentRunSchema = z.object({
|
|
116
|
+
schemaVersion: z.literal(1),
|
|
117
|
+
id: AgentRecordIdSchema,
|
|
118
|
+
conversationId: AgentRecordIdSchema,
|
|
119
|
+
inputMessageIds: z.array(AgentRecordIdSchema).min(1),
|
|
120
|
+
assistantMessageId: AgentRecordIdSchema,
|
|
121
|
+
state: AgentRunStateSchema,
|
|
122
|
+
revision: AgentRecordVersionSchema,
|
|
123
|
+
ownerId: z.string().min(1).optional(),
|
|
124
|
+
fencingToken: AgentRecordVersionSchema.optional(),
|
|
125
|
+
terminalReason: AgentTerminalReasonSchema.optional(),
|
|
126
|
+
terminalPolicyName: z.string().min(1).optional(),
|
|
127
|
+
createdAt: AgentTimestampSchema,
|
|
128
|
+
updatedAt: AgentTimestampSchema
|
|
129
|
+
});
|
|
130
|
+
var AgentSnapshotSchema = z.object({
|
|
131
|
+
schemaVersion: z.literal(1),
|
|
132
|
+
conversationId: AgentRecordIdSchema,
|
|
133
|
+
version: AgentRecordVersionSchema,
|
|
134
|
+
messages: z.array(AgentMessageSchema),
|
|
135
|
+
runs: z.array(AgentRunSchema)
|
|
136
|
+
});
|
|
137
|
+
var AgentUsageValueSchema = z.object({
|
|
138
|
+
value: z.number().nonnegative().optional(),
|
|
139
|
+
provenance: z.enum(["provider-reported", "computed", "estimated", "unavailable"])
|
|
140
|
+
});
|
|
141
|
+
var AgentCostValueSchema = z.object({
|
|
142
|
+
value: z.number().nonnegative().optional(),
|
|
143
|
+
currency: z.string().length(3).optional(),
|
|
144
|
+
provenance: z.enum(["provider-reported", "computed", "estimated", "unavailable"])
|
|
145
|
+
});
|
|
146
|
+
var AgentUsageSchema = z.object({
|
|
147
|
+
inputTokens: AgentUsageValueSchema,
|
|
148
|
+
outputTokens: AgentUsageValueSchema,
|
|
149
|
+
reasoningTokens: AgentUsageValueSchema.optional(),
|
|
150
|
+
cacheReadTokens: AgentUsageValueSchema.optional(),
|
|
151
|
+
cacheWriteTokens: AgentUsageValueSchema.optional(),
|
|
152
|
+
cost: AgentCostValueSchema.optional()
|
|
153
|
+
});
|
|
154
|
+
var AgentRunMetricsSchema = z.object({
|
|
155
|
+
partial: z.boolean(),
|
|
156
|
+
usage: AgentUsageSchema.optional(),
|
|
157
|
+
durationMs: z.number().nonnegative().optional(),
|
|
158
|
+
ttftMs: z.number().nonnegative().optional()
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
export { AgentRecordIdSchema, AgentRecordVersionSchema, AgentTimestampSchema, AgentJsonObjectSchema, AgentProviderEnvelopeSchema, AgentTextPartSchema, AgentReasoningPartSchema, AgentFilePartSchema, AgentSourcePartSchema, AgentToolCallPartSchema, AgentToolResultPartSchema, AgentOpaquePartSchema, AgentControlPartSchema, AgentMessagePartSchema, AgentMessageRoleSchema, AgentMessageStatusSchema, AgentMessageSchema, AgentAssistantPlaceholderSchema, AgentRunStateSchema, AgentTerminalReasonSchema, AgentRunSchema, AgentSnapshotSchema, AgentUsageValueSchema, AgentCostValueSchema, AgentUsageSchema, AgentRunMetricsSchema };
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
* Every project writes the same `onError`: turn a thrown value into one wire
|
|
6
6
|
* shape, mapping stitchkit's own error codes to the app's public codes. The map
|
|
7
7
|
* is partial — list the codes you have an opinion about, and an unlisted one
|
|
8
|
-
* travels as itself
|
|
8
|
+
* travels as itself unless `unmappedCode` supplies one declarative fallback.
|
|
9
|
+
* Codes the project throws on its own always pass through unchanged. A
|
|
9
10
|
* project whose envelope is a published contract adds `satisfies
|
|
10
11
|
* Record<StitchErrorCode, …>` to its own map and buys the stricter deal: a code
|
|
11
12
|
* added by a later release then breaks the build instead of reaching the wire
|
|
@@ -58,6 +59,12 @@ export interface ErrorHookConfig<TWireCode extends string = string> {
|
|
|
58
59
|
* error here. Codes you threw yourself (not stitchkit's) pass through as-is.
|
|
59
60
|
*/
|
|
60
61
|
codeMap?: Partial<Record<StitchErrorCode, TWireCode>>;
|
|
62
|
+
/**
|
|
63
|
+
* Wire code for every unmapped stitchkit code, or a resolver for grouping
|
|
64
|
+
* them. Explicit `codeMap` entries win. Project-owned codes never use this
|
|
65
|
+
* fallback and continue to pass through unchanged.
|
|
66
|
+
*/
|
|
67
|
+
unmappedCode?: TWireCode | ((code: StitchErrorCode) => TWireCode);
|
|
61
68
|
/** Build the response body from the resolved error. */
|
|
62
69
|
/**
|
|
63
70
|
* Build the response body from the resolved error. `ctx` is the request's
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-hook.d.ts","sourceRoot":"","sources":["../../src/server/error-hook.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"error-hook.d.ts","sourceRoot":"","sources":["../../src/server/error-hook.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAqB,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAEtE,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzD,uEAAuE;AACvE,MAAM,WAAW,aAAa;IAC5B,wFAAwF;IACxF,IAAI,EAAE,MAAM,CAAC;IACb,mBAAmB;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,+FAA+F;IAC/F,OAAO,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,6DAA6D;IAC7D,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,oCAAoC;AACpC,MAAM,WAAW,eAAe,CAAC,SAAS,SAAS,MAAM,GAAG,MAAM;IAChE;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,SAAS,CAAC,CAAC,CAAC;IACtD;;;;OAIG;IACH,YAAY,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,IAAI,EAAE,eAAe,KAAK,SAAS,CAAC,CAAC;IAClE,uDAAuD;IACvD;;;;;OAKG;IACH,MAAM,EAAE,CACN,IAAI,EAAE,aAAa,EACnB,GAAG,EAAE,cAAc,EACnB,QAAQ,CAAC,EAAE,SAAS,KACjB,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAChC;;;;OAIG;IACH,OAAO,CAAC,EAAE,CACR,KAAK,EAAE,OAAO,EACd,IAAI,EAAE,aAAa,EACnB,GAAG,EAAE,cAAc,EACnB,QAAQ,CAAC,EAAE,SAAS,KACjB,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACjC;AAED,mEAAmE;AACnE,wBAAgB,eAAe,CAAC,SAAS,SAAS,MAAM,GAAG,MAAM,EAC/D,MAAM,EAAE,eAAe,CAAC,SAAS,CAAC,GACjC,WAAW,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAkCxC"}
|
package/dist/server/index.js
CHANGED
|
@@ -351,8 +351,10 @@ function cacheHeaders(maxAge, scope = "public") {
|
|
|
351
351
|
function createErrorHook(config) {
|
|
352
352
|
return async (ctx, error, endpoint) => {
|
|
353
353
|
const appErr = normalizeError(error);
|
|
354
|
-
const
|
|
355
|
-
const
|
|
354
|
+
const stitchCode = isStitchErrorCode(appErr.code) ? appErr.code : undefined;
|
|
355
|
+
const mapped = stitchCode === undefined ? undefined : config.codeMap?.[stitchCode];
|
|
356
|
+
const fallback = mapped === undefined && stitchCode !== undefined ? typeof config.unmappedCode === "function" ? config.unmappedCode(stitchCode) : config.unmappedCode : undefined;
|
|
357
|
+
const code = mapped ?? fallback ?? appErr.code;
|
|
356
358
|
const info = {
|
|
357
359
|
code,
|
|
358
360
|
status: appErr.status,
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { AgentRuntimeStore } from '../agent-runtime/store';
|
|
2
|
+
export interface AgentStoreConformanceConfig {
|
|
3
|
+
createStore(): AgentRuntimeStore | Promise<AgentRuntimeStore>;
|
|
4
|
+
}
|
|
5
|
+
/** Black-box contract shared by memory and third-party durable agent stores. */
|
|
6
|
+
export declare function runAgentStoreConformance(config: AgentStoreConformanceConfig): Promise<void>;
|
|
7
|
+
//# sourceMappingURL=agent-store-conformance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-store-conformance.d.ts","sourceRoot":"","sources":["../../src/testing/agent-store-conformance.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAEhE,MAAM,WAAW,2BAA2B;IAC1C,WAAW,IAAI,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;CAC/D;AAwCD,gFAAgF;AAChF,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,2BAA2B,GAClC,OAAO,CAAC,IAAI,CAAC,CAmPf"}
|
package/dist/testing.d.ts
CHANGED
|
@@ -31,6 +31,8 @@ export declare function createHandlerTestClient<T extends Record<string, Endpoin
|
|
|
31
31
|
export declare function createHandlerTestClients<T extends Record<string, ContractDef<Record<string, EndpointDef>, string>>, TServer = unknown, const K extends string = never>(config: HandlerTestClientsConfig<T, TServer, K>): {
|
|
32
32
|
[P in keyof T]: ScopedHttpClient<T[P]['endpoints'], ScopedKeys<K>>;
|
|
33
33
|
};
|
|
34
|
+
export { type AgentRaceBarrier, type AgentRaceDriver, type AgentRaceTrace, type AgentRaceTraceEntry, createAgentRaceBarrier, createAgentRaceDriver, createAgentRaceTrace, } from './agent-runtime/testing';
|
|
35
|
+
export { type AgentStoreConformanceConfig, runAgentStoreConformance, } from './testing/agent-store-conformance';
|
|
34
36
|
export { assertSurfaceDiscovery, type ConformanceTransport, type CreateRealtimeProbeDriverConfig, createRealtimeProbeDriver, type DefineRealtimeProbeConfig, defineRealtimeProbe, type RealtimeDisconnectObservation, RealtimeDisconnectObservationSchema, type RealtimeProbeAdapter, type RealtimeProbeFixture, type RealtimeProbeScenario, type RealtimeRejectionObservation, RealtimeRejectionObservationSchema, type RunSurfaceProbesConfig, runSurfaceProbes, type SurfaceDiscoveryObservation, type SurfaceProbe, type SurfaceProbeDriver, type SurfaceRealtimeDiscoveryObservation, type SurfaceToolDiscoveryObservation, type TransportObservation, TransportObservationSchema, } from './testing/surface-conformance';
|
|
35
37
|
export { assertSurfaceManifestSnapshot, buildSurfaceManifest, type IncompatibleSchemaPolicy, type McpSchemaValidationConfig, type SurfaceAgentProjection, type SurfaceManifest, type SurfaceManifestConfig, type SurfaceManifestExtension, SurfaceManifestExtensionSchema, type SurfaceManifestOperation, SurfaceManifestOperationSchema, type SurfaceManifestRealtimeEvent, SurfaceManifestRealtimeEventSchema, SurfaceManifestSchema, type SurfaceManifestTool, SurfaceManifestToolSchema, type SurfaceManifestToolSurface, SurfaceManifestToolSurfaceSchema, type SurfaceMcpPreparation, SurfaceRealtimeSchemaPairSchema, type SurfaceRuntimeToolDefinition, SurfaceSchemaDigestsSchema, type SurfaceToolDefinition, type SurfaceToolExtension, serializeSurfaceValue, } from './testing/surface-manifest';
|
|
36
38
|
//# sourceMappingURL=testing.d.ts.map
|
package/dist/testing.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"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"}
|
package/dist/testing.js
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AgentMessageSchema,
|
|
3
|
+
AgentRunSchema
|
|
4
|
+
} from "./index-vtjgx3vv.js";
|
|
1
5
|
import {
|
|
2
6
|
RealtimeRequestDisconnectedError,
|
|
3
7
|
RealtimeRequestInvalidAcknowledgementError,
|
|
@@ -23,6 +27,329 @@ import {
|
|
|
23
27
|
} from "./index-smpbdg6k.js";
|
|
24
28
|
import"./index-1bx83sw4.js";
|
|
25
29
|
|
|
30
|
+
// src/agent-runtime/testing.ts
|
|
31
|
+
function createAgentRaceBarrier(timeoutMs = 5000) {
|
|
32
|
+
if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 1) {
|
|
33
|
+
throw new TypeError("Agent race barrier timeoutMs must be a positive safe integer");
|
|
34
|
+
}
|
|
35
|
+
const reached = Promise.withResolvers();
|
|
36
|
+
const released = Promise.withResolvers();
|
|
37
|
+
let announced = false;
|
|
38
|
+
return {
|
|
39
|
+
reached: reached.promise,
|
|
40
|
+
async wait() {
|
|
41
|
+
if (!announced) {
|
|
42
|
+
announced = true;
|
|
43
|
+
reached.resolve();
|
|
44
|
+
}
|
|
45
|
+
let timer;
|
|
46
|
+
try {
|
|
47
|
+
await Promise.race([
|
|
48
|
+
released.promise,
|
|
49
|
+
new Promise((_resolve, reject) => {
|
|
50
|
+
timer = setTimeout(() => reject(new Error(`Agent race barrier exceeded ${timeoutMs}ms teardown bound`)), timeoutMs);
|
|
51
|
+
})
|
|
52
|
+
]);
|
|
53
|
+
} finally {
|
|
54
|
+
if (timer !== undefined)
|
|
55
|
+
clearTimeout(timer);
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
release: released.resolve
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function createAgentRaceTrace() {
|
|
62
|
+
const recorded = [];
|
|
63
|
+
return {
|
|
64
|
+
record(name) {
|
|
65
|
+
const entry = { name, sequence: recorded.length };
|
|
66
|
+
recorded.push(entry);
|
|
67
|
+
return entry;
|
|
68
|
+
},
|
|
69
|
+
entries: () => recorded.map((entry) => ({ ...entry })),
|
|
70
|
+
assertBefore(first, second) {
|
|
71
|
+
const firstEntry = recorded.find((entry) => entry.name === first);
|
|
72
|
+
const secondEntry = recorded.find((entry) => entry.name === second);
|
|
73
|
+
if (!firstEntry || !secondEntry || firstEntry.sequence >= secondEntry.sequence) {
|
|
74
|
+
throw new Error(`Expected ${first} before ${second}`);
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
assertSequence(names) {
|
|
78
|
+
const actual = recorded.map((entry) => entry.name);
|
|
79
|
+
if (actual.length !== names.length || actual.some((name, index) => name !== names[index])) {
|
|
80
|
+
throw new Error(`Expected trace ${names.join(" -> ")}, received ${actual.join(" -> ")}`);
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
count: (name) => recorded.filter((entry) => entry.name === name).length
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function createAgentRaceDriver(timeoutMs = 5000) {
|
|
87
|
+
const trace = createAgentRaceTrace();
|
|
88
|
+
const barriers = new Map;
|
|
89
|
+
return {
|
|
90
|
+
trace,
|
|
91
|
+
barrier(name) {
|
|
92
|
+
const existing = barriers.get(name);
|
|
93
|
+
if (existing)
|
|
94
|
+
return existing;
|
|
95
|
+
const created = createAgentRaceBarrier(timeoutMs);
|
|
96
|
+
barriers.set(name, created);
|
|
97
|
+
return created;
|
|
98
|
+
},
|
|
99
|
+
releaseAll() {
|
|
100
|
+
for (const barrier of barriers.values())
|
|
101
|
+
barrier.release();
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
// src/testing/agent-store-conformance.ts
|
|
106
|
+
function userMessage(conversationId, id) {
|
|
107
|
+
return AgentMessageSchema.parse({
|
|
108
|
+
schemaVersion: 1,
|
|
109
|
+
id,
|
|
110
|
+
conversationId,
|
|
111
|
+
role: "user",
|
|
112
|
+
status: "committed",
|
|
113
|
+
parts: [{ type: "text", text: id }],
|
|
114
|
+
createdAt: "2026-08-22T00:00:00.000Z",
|
|
115
|
+
updatedAt: "2026-08-22T00:00:00.000Z"
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
function queuedRun(conversationId, inputMessageId, id) {
|
|
119
|
+
return AgentRunSchema.parse({
|
|
120
|
+
schemaVersion: 1,
|
|
121
|
+
id,
|
|
122
|
+
conversationId,
|
|
123
|
+
inputMessageIds: [inputMessageId],
|
|
124
|
+
assistantMessageId: `${id}-assistant`,
|
|
125
|
+
state: "queued",
|
|
126
|
+
revision: 0,
|
|
127
|
+
createdAt: "2026-08-22T00:00:00.000Z",
|
|
128
|
+
updatedAt: "2026-08-22T00:00:00.000Z"
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
function requireOutcome(actual, expected) {
|
|
132
|
+
if (actual.outcome !== expected) {
|
|
133
|
+
throw new Error(`Agent store conformance expected ${expected}, received ${actual.outcome}`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
async function runAgentStoreConformance(config) {
|
|
137
|
+
const store = await config.createStore();
|
|
138
|
+
const conversationId = `conformance-${crypto.randomUUID()}`;
|
|
139
|
+
const firstInput = userMessage(conversationId, "input-1");
|
|
140
|
+
const firstRun = queuedRun(conversationId, firstInput.id, "run-1");
|
|
141
|
+
const accepted = await store.acceptInputAndAssignRun({
|
|
142
|
+
idempotencyKey: "request-1",
|
|
143
|
+
input: firstInput,
|
|
144
|
+
run: firstRun
|
|
145
|
+
});
|
|
146
|
+
requireOutcome(accepted, "applied");
|
|
147
|
+
const duplicate = await store.acceptInputAndAssignRun({
|
|
148
|
+
idempotencyKey: "request-1",
|
|
149
|
+
input: userMessage(conversationId, "discarded-input"),
|
|
150
|
+
run: queuedRun(conversationId, "discarded-input", "discarded-run")
|
|
151
|
+
});
|
|
152
|
+
requireOutcome(duplicate, "duplicate");
|
|
153
|
+
if (duplicate.input.id !== firstInput.id || duplicate.inputMessageId !== firstInput.id || duplicate.runId !== firstRun.id || duplicate.assistantMessageId !== firstRun.assistantMessageId) {
|
|
154
|
+
throw new Error("Duplicate admission did not return its original durable identity");
|
|
155
|
+
}
|
|
156
|
+
const secondInput = userMessage(conversationId, "input-2");
|
|
157
|
+
const coalesced = await store.acceptInputAndAssignRun({
|
|
158
|
+
idempotencyKey: "request-2",
|
|
159
|
+
input: secondInput,
|
|
160
|
+
run: queuedRun(conversationId, secondInput.id, "discarded-coalesced-run"),
|
|
161
|
+
coalesceIntoRunId: firstRun.id
|
|
162
|
+
});
|
|
163
|
+
requireOutcome(coalesced, "applied");
|
|
164
|
+
const assigned = coalesced.snapshot.runs.find((run) => run.id === firstRun.id);
|
|
165
|
+
if (assigned?.inputMessageIds.join(",") !== "input-1,input-2") {
|
|
166
|
+
throw new Error("Coalesced admission did not preserve ordered input identities");
|
|
167
|
+
}
|
|
168
|
+
const collidingInput = userMessage(conversationId, assigned.assistantMessageId);
|
|
169
|
+
await store.acceptInputAndAssignRun({
|
|
170
|
+
idempotencyKey: "request-collision",
|
|
171
|
+
input: collidingInput,
|
|
172
|
+
run: queuedRun(conversationId, collidingInput.id, "discarded-collision-run"),
|
|
173
|
+
coalesceIntoRunId: assigned.id
|
|
174
|
+
}).then(() => {
|
|
175
|
+
throw new Error("Coalesced input reused the reserved assistant identity");
|
|
176
|
+
}, (error) => {
|
|
177
|
+
if (!(error instanceof TypeError))
|
|
178
|
+
throw error;
|
|
179
|
+
});
|
|
180
|
+
await store.replaceCompactedRange({
|
|
181
|
+
conversationId,
|
|
182
|
+
expectedVersion: coalesced.snapshot.version,
|
|
183
|
+
replacedMessageIds: [firstInput.id, secondInput.id],
|
|
184
|
+
summary: AgentMessageSchema.parse({
|
|
185
|
+
schemaVersion: 1,
|
|
186
|
+
id: assigned.assistantMessageId,
|
|
187
|
+
conversationId,
|
|
188
|
+
role: "summary",
|
|
189
|
+
status: "committed",
|
|
190
|
+
parts: [{ type: "text", text: "invalid reserved identity" }],
|
|
191
|
+
createdAt: "2026-08-22T00:00:02.000Z",
|
|
192
|
+
updatedAt: "2026-08-22T00:00:02.000Z"
|
|
193
|
+
})
|
|
194
|
+
}).then(() => {
|
|
195
|
+
throw new Error("Compaction reused a reserved assistant identity");
|
|
196
|
+
}, (error) => {
|
|
197
|
+
if (!(error instanceof TypeError))
|
|
198
|
+
throw error;
|
|
199
|
+
});
|
|
200
|
+
const compacted = await store.replaceCompactedRange({
|
|
201
|
+
conversationId,
|
|
202
|
+
expectedVersion: coalesced.snapshot.version,
|
|
203
|
+
replacedMessageIds: [firstInput.id, secondInput.id],
|
|
204
|
+
summary: AgentMessageSchema.parse({
|
|
205
|
+
schemaVersion: 1,
|
|
206
|
+
id: "summary-1",
|
|
207
|
+
conversationId,
|
|
208
|
+
role: "summary",
|
|
209
|
+
status: "committed",
|
|
210
|
+
parts: [{ type: "text", text: "two inputs" }],
|
|
211
|
+
createdAt: "2026-08-22T00:00:02.000Z",
|
|
212
|
+
updatedAt: "2026-08-22T00:00:02.000Z"
|
|
213
|
+
})
|
|
214
|
+
});
|
|
215
|
+
requireOutcome(compacted, "applied");
|
|
216
|
+
const duplicateAfterCompaction = await store.acceptInputAndAssignRun({
|
|
217
|
+
idempotencyKey: "request-1",
|
|
218
|
+
input: userMessage(conversationId, "discarded-after-compaction"),
|
|
219
|
+
run: queuedRun(conversationId, "discarded-after-compaction", "discarded-run-2")
|
|
220
|
+
});
|
|
221
|
+
requireOutcome(duplicateAfterCompaction, "duplicate");
|
|
222
|
+
if (duplicateAfterCompaction.input.id !== firstInput.id) {
|
|
223
|
+
throw new Error("Compaction discarded the canonical duplicate admission input");
|
|
224
|
+
}
|
|
225
|
+
const acquired = await store.acquireRun({
|
|
226
|
+
conversationId,
|
|
227
|
+
runId: assigned.id,
|
|
228
|
+
expectedRevision: assigned.revision,
|
|
229
|
+
ownerId: "conformance-owner"
|
|
230
|
+
});
|
|
231
|
+
requireOutcome(acquired, "applied");
|
|
232
|
+
const running = acquired.snapshot.runs.find((run) => run.id === assigned.id);
|
|
233
|
+
if (!running)
|
|
234
|
+
throw new Error("Acquired run disappeared");
|
|
235
|
+
const stale = await store.checkpointRunAssistant({
|
|
236
|
+
conversationId,
|
|
237
|
+
runId: running.id,
|
|
238
|
+
expectedRevision: running.revision - 1,
|
|
239
|
+
ownerId: "conformance-owner",
|
|
240
|
+
assistant: AgentMessageSchema.parse({
|
|
241
|
+
schemaVersion: 1,
|
|
242
|
+
id: running.assistantMessageId,
|
|
243
|
+
conversationId,
|
|
244
|
+
runId: running.id,
|
|
245
|
+
role: "assistant",
|
|
246
|
+
status: "streaming",
|
|
247
|
+
parts: [],
|
|
248
|
+
createdAt: "2026-08-22T00:00:00.000Z",
|
|
249
|
+
updatedAt: "2026-08-22T00:00:01.000Z"
|
|
250
|
+
})
|
|
251
|
+
});
|
|
252
|
+
requireOutcome(stale, "conflict");
|
|
253
|
+
await store.recoverRun({
|
|
254
|
+
conversationId,
|
|
255
|
+
runId: running.id,
|
|
256
|
+
expectedRevision: running.revision,
|
|
257
|
+
action: "requeue"
|
|
258
|
+
}).then(() => {
|
|
259
|
+
throw new Error("Acquired recovery replayed without explicit safety evidence");
|
|
260
|
+
}, (error) => {
|
|
261
|
+
if (!(error instanceof TypeError))
|
|
262
|
+
throw error;
|
|
263
|
+
});
|
|
264
|
+
const checkpoint = await store.checkpointRunAssistant({
|
|
265
|
+
conversationId,
|
|
266
|
+
runId: running.id,
|
|
267
|
+
expectedRevision: running.revision,
|
|
268
|
+
ownerId: "conformance-owner",
|
|
269
|
+
assistant: AgentMessageSchema.parse({
|
|
270
|
+
schemaVersion: 1,
|
|
271
|
+
id: running.assistantMessageId,
|
|
272
|
+
conversationId,
|
|
273
|
+
runId: running.id,
|
|
274
|
+
role: "assistant",
|
|
275
|
+
status: "streaming",
|
|
276
|
+
parts: [{ type: "text", text: "checkpoint" }],
|
|
277
|
+
createdAt: "2026-08-22T00:00:00.000Z",
|
|
278
|
+
updatedAt: "2026-08-22T00:00:01.000Z"
|
|
279
|
+
})
|
|
280
|
+
});
|
|
281
|
+
requireOutcome(checkpoint, "applied");
|
|
282
|
+
const checkpointedRun = checkpoint.snapshot.runs.find((run) => run.id === running.id);
|
|
283
|
+
if (!checkpointedRun)
|
|
284
|
+
throw new Error("Checkpointed run disappeared");
|
|
285
|
+
const terminalAssistant = AgentMessageSchema.parse({
|
|
286
|
+
schemaVersion: 1,
|
|
287
|
+
id: running.assistantMessageId,
|
|
288
|
+
conversationId,
|
|
289
|
+
runId: running.id,
|
|
290
|
+
role: "assistant",
|
|
291
|
+
status: "completed",
|
|
292
|
+
parts: [{ type: "text", text: "done" }],
|
|
293
|
+
createdAt: "2026-08-22T00:00:00.000Z",
|
|
294
|
+
updatedAt: "2026-08-22T00:00:02.000Z"
|
|
295
|
+
});
|
|
296
|
+
const terminalResults = await Promise.all([
|
|
297
|
+
store.commitRunTerminal({
|
|
298
|
+
conversationId,
|
|
299
|
+
runId: running.id,
|
|
300
|
+
expectedRevision: checkpointedRun.revision,
|
|
301
|
+
ownerId: "conformance-owner",
|
|
302
|
+
assistant: terminalAssistant,
|
|
303
|
+
reason: "success"
|
|
304
|
+
}),
|
|
305
|
+
store.commitRunTerminal({
|
|
306
|
+
conversationId,
|
|
307
|
+
runId: running.id,
|
|
308
|
+
expectedRevision: checkpointedRun.revision,
|
|
309
|
+
ownerId: "conformance-owner",
|
|
310
|
+
assistant: terminalAssistant,
|
|
311
|
+
reason: "success"
|
|
312
|
+
})
|
|
313
|
+
]);
|
|
314
|
+
const terminalOutcomes = terminalResults.map((result) => result.outcome).sort();
|
|
315
|
+
if (terminalOutcomes.join(",") !== "applied,conflict") {
|
|
316
|
+
throw new Error(`Terminal race was not linearized: ${terminalOutcomes.join(",")}`);
|
|
317
|
+
}
|
|
318
|
+
const recoveryConversationId = `${conversationId}-recovery`;
|
|
319
|
+
const recoveryInput = userMessage(recoveryConversationId, "recovery-input");
|
|
320
|
+
const recoveryRun = queuedRun(recoveryConversationId, recoveryInput.id, "recovery-run");
|
|
321
|
+
const recoveryAccepted = await store.acceptInputAndAssignRun({
|
|
322
|
+
idempotencyKey: "recovery-request",
|
|
323
|
+
input: recoveryInput,
|
|
324
|
+
run: recoveryRun
|
|
325
|
+
});
|
|
326
|
+
requireOutcome(recoveryAccepted, "applied");
|
|
327
|
+
const recoveryAssigned = recoveryAccepted.snapshot.runs.find((run) => run.id === recoveryRun.id);
|
|
328
|
+
if (!recoveryAssigned)
|
|
329
|
+
throw new Error("Recovery run disappeared after admission");
|
|
330
|
+
const recoveryAcquired = await store.acquireRun({
|
|
331
|
+
conversationId: recoveryConversationId,
|
|
332
|
+
runId: recoveryAssigned.id,
|
|
333
|
+
expectedRevision: recoveryAssigned.revision,
|
|
334
|
+
ownerId: "abandoned-owner"
|
|
335
|
+
});
|
|
336
|
+
requireOutcome(recoveryAcquired, "applied");
|
|
337
|
+
const abandonedRun = recoveryAcquired.snapshot.runs.find((run) => run.id === recoveryRun.id);
|
|
338
|
+
if (!abandonedRun)
|
|
339
|
+
throw new Error("Recovery run disappeared after acquisition");
|
|
340
|
+
const abandoned = await store.recoverRun({
|
|
341
|
+
conversationId: recoveryConversationId,
|
|
342
|
+
runId: abandonedRun.id,
|
|
343
|
+
expectedRevision: abandonedRun.revision,
|
|
344
|
+
action: "abandon"
|
|
345
|
+
});
|
|
346
|
+
requireOutcome(abandoned, "applied");
|
|
347
|
+
const terminalRun = abandoned.snapshot.runs.find((run) => run.id === abandonedRun.id);
|
|
348
|
+
const terminalMessage = abandoned.snapshot.messages.find((message) => message.id === abandonedRun.assistantMessageId);
|
|
349
|
+
if (terminalRun?.state !== "abandoned" || terminalMessage?.status !== "failed") {
|
|
350
|
+
throw new Error("Abandon recovery did not atomically terminalize its assistant record");
|
|
351
|
+
}
|
|
352
|
+
}
|
|
26
353
|
// src/testing/surface-conformance.ts
|
|
27
354
|
import { z as z2 } from "zod";
|
|
28
355
|
|
|
@@ -740,10 +1067,14 @@ export {
|
|
|
740
1067
|
assertSurfaceDiscovery,
|
|
741
1068
|
assertSurfaceManifestSnapshot,
|
|
742
1069
|
buildSurfaceManifest,
|
|
1070
|
+
createAgentRaceBarrier,
|
|
1071
|
+
createAgentRaceDriver,
|
|
1072
|
+
createAgentRaceTrace,
|
|
743
1073
|
createHandlerTestClient,
|
|
744
1074
|
createHandlerTestClients,
|
|
745
1075
|
createRealtimeProbeDriver,
|
|
746
1076
|
defineRealtimeProbe,
|
|
1077
|
+
runAgentStoreConformance,
|
|
747
1078
|
runSurfaceProbes,
|
|
748
1079
|
serializeSurfaceValue
|
|
749
1080
|
};
|