@rynfar/meridian 1.64.0 → 1.65.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/{cli-4ghkaajs.js → cli-7cts44b5.js} +1167 -67
- package/dist/{cli-pbvm9kc2.js → cli-n8t34zmq.js} +203 -24
- package/dist/{cli-m0p2bc8v.js → cli-pdpry6q0.js} +16 -3
- package/dist/cli.js +6 -6
- package/dist/meridian-v2.js +241 -33
- package/dist/{profiles-0pyeqayw.js → profiles-4ajzjqhm.js} +1 -1
- package/dist/proxy/adapter.d.ts +16 -0
- package/dist/proxy/adapter.d.ts.map +1 -1
- package/dist/proxy/adapters/opencode.d.ts.map +1 -1
- package/dist/proxy/errors.d.ts.map +1 -1
- package/dist/proxy/priorityAttestation.d.ts +35 -0
- package/dist/proxy/priorityAttestation.d.ts.map +1 -0
- package/dist/proxy/routing.d.ts +16 -2
- package/dist/proxy/routing.d.ts.map +1 -1
- package/dist/proxy/server.d.ts.map +1 -1
- package/dist/proxy/session/cache.d.ts +25 -2
- package/dist/proxy/session/cache.d.ts.map +1 -1
- package/dist/proxy/session/lineage.d.ts +1 -1
- package/dist/proxy/session/lineage.d.ts.map +1 -1
- package/dist/proxy/session/turnCoordinator.d.ts +2 -0
- package/dist/proxy/session/turnCoordinator.d.ts.map +1 -1
- package/dist/proxy/sessionStore.d.ts +133 -0
- package/dist/proxy/sessionStore.d.ts.map +1 -1
- package/dist/proxy/settings.d.ts +2 -0
- package/dist/proxy/settings.d.ts.map +1 -1
- package/dist/proxy/setup.d.ts.map +1 -1
- package/dist/server.js +3 -3
- package/dist/{setup-4v3zg3c0.js → setup-8fwgwhqh.js} +1 -1
- package/package.json +2 -2
- package/plugin/meridian-v2.ts +185 -40
- package/plugin/meridian.ts +125 -20
- package/plugin/priority-attestation.ts +150 -0
|
@@ -51,9 +51,37 @@ export interface StoredSession {
|
|
|
51
51
|
previousTranscript?: TranscriptLocator;
|
|
52
52
|
}
|
|
53
53
|
export type StoredSessionGeneration = string;
|
|
54
|
+
export interface DurablePriorityAssignment {
|
|
55
|
+
profileId: string;
|
|
56
|
+
lastHumanTurnDigest: string;
|
|
57
|
+
/** Monotonic signed issue-time high-water mark for replay suppression. */
|
|
58
|
+
lastHumanTurnIssuedAt: number;
|
|
59
|
+
mappingKey: string;
|
|
60
|
+
/** Exact mapping generation published atomically with this route. */
|
|
61
|
+
mappingGeneration: StoredSessionGeneration;
|
|
62
|
+
/** Unique route publication token. Replaced on every route mutation. */
|
|
63
|
+
generationId: string;
|
|
64
|
+
updatedAt: number;
|
|
65
|
+
}
|
|
66
|
+
export type PriorityAssignmentGeneration = string;
|
|
67
|
+
export interface DurablePriorityAttempt {
|
|
68
|
+
/** A prior exposed or crashed attempt blocks untrusted/same-turn replay. */
|
|
69
|
+
blocked: boolean;
|
|
70
|
+
blockedTurnDigest: string | null;
|
|
71
|
+
blockedTurnIssuedAt: number | null;
|
|
72
|
+
/** One exact in-flight request owns publication/release for this route. */
|
|
73
|
+
pendingTurnDigest: string | null;
|
|
74
|
+
pendingTurnIssuedAt: number | null;
|
|
75
|
+
ownerToken: string | null;
|
|
76
|
+
generationId: string;
|
|
77
|
+
updatedAt: number;
|
|
78
|
+
}
|
|
54
79
|
/** Exact, key-bound durable generation used for compare-and-swap fencing. */
|
|
55
80
|
export declare function getStoredSessionGeneration(session: StoredSession, key: string): StoredSessionGeneration;
|
|
81
|
+
export declare function getPriorityAssignmentGeneration(assignment: DurablePriorityAssignment, routeKey: string): PriorityAssignmentGeneration;
|
|
56
82
|
export declare function getMaxStoredSessionsLimit(): number;
|
|
83
|
+
export declare function getMaxPriorityAssignmentsLimit(): number;
|
|
84
|
+
export declare function getMaxPriorityAttemptsLimit(): number;
|
|
57
85
|
/** Set an explicit session store directory. Takes priority over env var.
|
|
58
86
|
* Pass null to clear. For testing only. The legacy options parameter remains
|
|
59
87
|
* accepted for compatibility, but transactions are always locked. */
|
|
@@ -82,9 +110,114 @@ export type SharedSessionLookupResult = {
|
|
|
82
110
|
/** Distinguish an authoritative absence from a transient/corrupt read. */
|
|
83
111
|
export declare function lookupSharedSessionResult(key: string): SharedSessionLookupResult;
|
|
84
112
|
export declare function lookupSharedSession(key: string): StoredSession | undefined;
|
|
113
|
+
export type PriorityAssignmentLookupResult = {
|
|
114
|
+
status: "found";
|
|
115
|
+
assignment: DurablePriorityAssignment;
|
|
116
|
+
generation: PriorityAssignmentGeneration;
|
|
117
|
+
attempt?: DurablePriorityAttempt;
|
|
118
|
+
} | {
|
|
119
|
+
status: "missing";
|
|
120
|
+
generation: PriorityAssignmentGeneration;
|
|
121
|
+
attempt?: DurablePriorityAttempt;
|
|
122
|
+
} | {
|
|
123
|
+
status: "error";
|
|
124
|
+
error: Error;
|
|
125
|
+
};
|
|
126
|
+
/** Read one exact durable route. V1 documents authoritatively contain none. */
|
|
127
|
+
export declare function lookupPriorityAssignmentResult(routeKey: string): PriorityAssignmentLookupResult;
|
|
85
128
|
export declare function lookupSharedSessionByClaudeIdResult(claudeSessionId: string): SharedSessionLookupResult;
|
|
86
129
|
export declare function lookupSharedSessionByClaudeId(claudeSessionId: string): StoredSession | undefined;
|
|
87
130
|
export declare function storeSharedSession(key: string, claudeSessionId: string, messageCount?: number, lineageHash?: string, messageHashes?: string[], sdkMessageUuids?: Array<string | null>, contextUsage?: TokenUsage, messageBlockHashes?: string[][], passthroughToolCallAssistantUuid?: string | null, passthroughToolCallIds?: string[] | null, currentTranscript?: TranscriptLocator, sourceTranscript?: TranscriptLocator, expectedGeneration?: StoredSessionGeneration | null): StoredSessionGeneration | false;
|
|
131
|
+
export interface PriorityAttemptTurn {
|
|
132
|
+
turnId: string;
|
|
133
|
+
issuedAt: number;
|
|
134
|
+
}
|
|
135
|
+
export interface PriorityAttemptClaim {
|
|
136
|
+
ownerToken: string;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Reserve one durable route attempt before any SDK work can become exposed.
|
|
140
|
+
* A blocked/crashed attempt can be superseded only by a strictly newer trusted
|
|
141
|
+
* human turn. The prior blocker remains until the newer turn publishes.
|
|
142
|
+
*/
|
|
143
|
+
export declare function claimPriorityAttempt(options: {
|
|
144
|
+
routeKey: string;
|
|
145
|
+
expectedAssignmentGeneration: PriorityAssignmentGeneration;
|
|
146
|
+
turn?: PriorityAttemptTurn;
|
|
147
|
+
}): PriorityAttemptClaim | false;
|
|
148
|
+
/** Release an unexposed attempt; an older blocker remains intact. */
|
|
149
|
+
export declare function releasePriorityAttempt(routeKey: string, ownerToken: string): boolean;
|
|
150
|
+
/** Persist exposure before returning an account-shaped error or cancellation. */
|
|
151
|
+
export declare function blockPriorityAttempt(routeKey: string, ownerToken: string): boolean;
|
|
152
|
+
export interface SharedSessionPriorityPublication {
|
|
153
|
+
routeKey: string;
|
|
154
|
+
profileId: string;
|
|
155
|
+
lastHumanTurnDigest: string;
|
|
156
|
+
lastHumanTurnIssuedAt: number;
|
|
157
|
+
expectedAssignmentGeneration: PriorityAssignmentGeneration;
|
|
158
|
+
}
|
|
159
|
+
export interface SharedSessionAndPriorityAssignmentOptions {
|
|
160
|
+
key: string;
|
|
161
|
+
claudeSessionId: string;
|
|
162
|
+
messageCount: number;
|
|
163
|
+
lineageHash: string;
|
|
164
|
+
messageHashes: string[];
|
|
165
|
+
sdkMessageUuids?: Array<string | null>;
|
|
166
|
+
contextUsage?: TokenUsage;
|
|
167
|
+
messageBlockHashes: string[][];
|
|
168
|
+
passthroughToolCallAssistantUuid?: string | null;
|
|
169
|
+
passthroughToolCallIds?: string[] | null;
|
|
170
|
+
currentTranscript?: TranscriptLocator;
|
|
171
|
+
sourceTranscript?: TranscriptLocator;
|
|
172
|
+
expectedMappingGeneration: StoredSessionGeneration;
|
|
173
|
+
/** Original routed mapping retained across chained publications for rollback. */
|
|
174
|
+
rollbackMappingKey?: string;
|
|
175
|
+
/** Exact pre-SDK durable claim cleared only by this winning publication. */
|
|
176
|
+
attemptOwnerToken?: string;
|
|
177
|
+
priority: SharedSessionPriorityPublication;
|
|
178
|
+
}
|
|
179
|
+
export interface SharedSessionAndPriorityAssignmentResult {
|
|
180
|
+
mappingGeneration: StoredSessionGeneration;
|
|
181
|
+
assignmentGeneration: PriorityAssignmentGeneration;
|
|
182
|
+
previousMapping: StoredSession | null;
|
|
183
|
+
previousAssignment: DurablePriorityAssignment | null;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Publish one session mapping and its selected priority route as one locked,
|
|
187
|
+
* durable compare-and-swap. A v1 document upgrades only when this transaction
|
|
188
|
+
* wins; all ordinary mapping writes preserve either input version.
|
|
189
|
+
*/
|
|
190
|
+
export declare function storeSharedSessionAndPriorityAssignment(options: SharedSessionAndPriorityAssignmentOptions): SharedSessionAndPriorityAssignmentResult | false;
|
|
191
|
+
export interface FinalizeSharedSessionAndPriorityAssignmentOptions {
|
|
192
|
+
key: string;
|
|
193
|
+
routeKey: string;
|
|
194
|
+
expectedMappingGeneration: StoredSessionGeneration;
|
|
195
|
+
expectedAssignmentGeneration: PriorityAssignmentGeneration;
|
|
196
|
+
rollbackMappingKey?: string;
|
|
197
|
+
attemptOwnerToken?: string;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Make a successful publication irrevocable and prune its rollback backlog.
|
|
201
|
+
* Exact route+mapping CAS prevents a late finalizer from touching newer work.
|
|
202
|
+
*/
|
|
203
|
+
export declare function finalizeSharedSessionAndPriorityAssignment(options: FinalizeSharedSessionAndPriorityAssignmentOptions): boolean;
|
|
204
|
+
export interface RollbackSharedSessionAndPriorityAssignmentOptions {
|
|
205
|
+
key: string;
|
|
206
|
+
routeKey: string;
|
|
207
|
+
expectedMappingGeneration: StoredSessionGeneration;
|
|
208
|
+
expectedAssignmentGeneration: PriorityAssignmentGeneration;
|
|
209
|
+
previousMapping: StoredSession | null;
|
|
210
|
+
previousAssignment: DurablePriorityAssignment | null;
|
|
211
|
+
attemptOwnerToken?: string;
|
|
212
|
+
}
|
|
213
|
+
export interface RollbackSharedSessionAndPriorityAssignmentResult {
|
|
214
|
+
mappingGeneration: StoredSessionGeneration;
|
|
215
|
+
assignmentGeneration: PriorityAssignmentGeneration;
|
|
216
|
+
restoredMapping: StoredSession | null;
|
|
217
|
+
restoredAssignment: DurablePriorityAssignment | null;
|
|
218
|
+
}
|
|
219
|
+
/** Restore the exact pre-request authorities after a canceled late publication. */
|
|
220
|
+
export declare function rollbackSharedSessionAndPriorityAssignment(options: RollbackSharedSessionAndPriorityAssignmentOptions): RollbackSharedSessionAndPriorityAssignmentResult | false;
|
|
88
221
|
/** Attach an exact transcript locator without changing lineage or SDK identity.
|
|
89
222
|
* The durable revision advances so concurrent readers cannot miss the mutation. */
|
|
90
223
|
export declare function attachSharedTranscriptLocator(key: string, expectedClaudeSessionId: string, locator: TranscriptLocator, expectedGeneration?: StoredSessionGeneration): StoredSessionGeneration | false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessionStore.d.ts","sourceRoot":"","sources":["../../src/proxy/sessionStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AA2BH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAgBnD,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,wEAAwE;IACxE,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,eAAe,EAAE,MAAM,CAAA;IACvB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,4EAA4E;IAC5E,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;IACpB,gFAAgF;IAChF,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,6EAA6E;IAC7E,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,mFAAmF;IACnF,kBAAkB,CAAC,EAAE,MAAM,EAAE,EAAE,CAAA;IAC/B,iFAAiF;IACjF,eAAe,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IACtC;oFACgF;IAChF,gCAAgC,CAAC,EAAE,MAAM,CAAA;IACzC,qEAAqE;IACrE,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAA;IACjC,wDAAwD;IACxD,YAAY,CAAC,EAAE,UAAU,CAAA;IACzB;;kEAE8D;IAC9D,uBAAuB,CAAC,EAAE,MAAM,CAAA;IAChC,gEAAgE;IAChE,iBAAiB,CAAC,EAAE,iBAAiB,CAAA;IACrC,yEAAyE;IACzE,kBAAkB,CAAC,EAAE,iBAAiB,CAAA;CACvC;AAED,MAAM,MAAM,uBAAuB,GAAG,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"sessionStore.d.ts","sourceRoot":"","sources":["../../src/proxy/sessionStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AA2BH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAgBnD,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,wEAAwE;IACxE,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,eAAe,EAAE,MAAM,CAAA;IACvB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,4EAA4E;IAC5E,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;IACpB,gFAAgF;IAChF,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,6EAA6E;IAC7E,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,mFAAmF;IACnF,kBAAkB,CAAC,EAAE,MAAM,EAAE,EAAE,CAAA;IAC/B,iFAAiF;IACjF,eAAe,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IACtC;oFACgF;IAChF,gCAAgC,CAAC,EAAE,MAAM,CAAA;IACzC,qEAAqE;IACrE,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAA;IACjC,wDAAwD;IACxD,YAAY,CAAC,EAAE,UAAU,CAAA;IACzB;;kEAE8D;IAC9D,uBAAuB,CAAC,EAAE,MAAM,CAAA;IAChC,gEAAgE;IAChE,iBAAiB,CAAC,EAAE,iBAAiB,CAAA;IACrC,yEAAyE;IACzE,kBAAkB,CAAC,EAAE,iBAAiB,CAAA;CACvC;AAED,MAAM,MAAM,uBAAuB,GAAG,MAAM,CAAA;AAM5C,MAAM,WAAW,yBAAyB;IACxC,SAAS,EAAE,MAAM,CAAA;IACjB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,0EAA0E;IAC1E,qBAAqB,EAAE,MAAM,CAAA;IAC7B,UAAU,EAAE,MAAM,CAAA;IAClB,qEAAqE;IACrE,iBAAiB,EAAE,uBAAuB,CAAA;IAC1C,wEAAwE;IACxE,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,MAAM,4BAA4B,GAAG,MAAM,CAAA;AAEjD,MAAM,WAAW,sBAAsB;IACrC,4EAA4E;IAC5E,OAAO,EAAE,OAAO,CAAA;IAChB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,2EAA2E;IAC3E,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;CAClB;AA8CD,6EAA6E;AAC7E,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,aAAa,EACtB,GAAG,EAAE,MAAM,GACV,uBAAuB,CAIzB;AAqBD,wBAAgB,+BAA+B,CAC7C,UAAU,EAAE,yBAAyB,EACrC,QAAQ,EAAE,MAAM,GACf,4BAA4B,CAE9B;AAgCD,wBAAgB,yBAAyB,IAAI,MAAM,CAMlD;AAED,wBAAgB,8BAA8B,IAAI,MAAM,CAMvD;AAED,wBAAgB,2BAA2B,IAAI,MAAM,CAMpD;AA4WD;;sEAEsE;AACtE,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAE9F;AAED,uEAAuE;AACvE,wBAAgB,kBAAkB,IAAI,MAAM,CAK3C;AA+WD;2EAC2E;AAC3E,wBAAgB,wBAAwB,IAAI,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAExE;AAED,qFAAqF;AACrF,wBAAgB,kCAAkC,CAChD,gBAAgB,EAAE,MAAM,EACxB,UAAU,GAAE,SAAS,MAAM,EAAO,GACjC,MAAM,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAezC;AAqED,MAAM,MAAM,yBAAyB,GACjC;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,aAAa,CAAC;IAAC,UAAU,CAAC,EAAE,uBAAuB,CAAA;CAAE,GACjF;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,EAAE,aAAa,CAAC;IAAC,UAAU,CAAC,EAAE,uBAAuB,CAAA;CAAE,GACrF;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,CAAA;AAErC,0EAA0E;AAC1E,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,yBAAyB,CAgBhF;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAG1E;AAED,MAAM,MAAM,8BAA8B,GACtC;IACE,MAAM,EAAE,OAAO,CAAA;IACf,UAAU,EAAE,yBAAyB,CAAA;IACrC,UAAU,EAAE,4BAA4B,CAAA;IACxC,OAAO,CAAC,EAAE,sBAAsB,CAAA;CACjC,GACD;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,UAAU,EAAE,4BAA4B,CAAC;IAAC,OAAO,CAAC,EAAE,sBAAsB,CAAA;CAAE,GACjG;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,CAAA;AAErC,+EAA+E;AAC/E,wBAAgB,8BAA8B,CAAC,QAAQ,EAAE,MAAM,GAAG,8BAA8B,CAkB/F;AAED,wBAAgB,mCAAmC,CAAC,eAAe,EAAE,MAAM,GAAG,yBAAyB,CAoBtG;AAED,wBAAgB,6BAA6B,CAAC,eAAe,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAGhG;AAuBD,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,MAAM,EACX,eAAe,EAAE,MAAM,EACvB,YAAY,CAAC,EAAE,MAAM,EACrB,WAAW,CAAC,EAAE,MAAM,EACpB,aAAa,CAAC,EAAE,MAAM,EAAE,EACxB,eAAe,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,EACtC,YAAY,CAAC,EAAE,UAAU,EACzB,kBAAkB,CAAC,EAAE,MAAM,EAAE,EAAE,EAC/B,gCAAgC,CAAC,EAAE,MAAM,GAAG,IAAI,EAChD,sBAAsB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,EACxC,iBAAiB,CAAC,EAAE,iBAAiB,EACrC,gBAAgB,CAAC,EAAE,iBAAiB,EACpC,kBAAkB,CAAC,EAAE,uBAAuB,GAAG,IAAI,GAClD,uBAAuB,GAAG,KAAK,CAqGjC;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAA;CACnB;AAWD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE;IAC5C,QAAQ,EAAE,MAAM,CAAA;IAChB,4BAA4B,EAAE,4BAA4B,CAAA;IAC1D,IAAI,CAAC,EAAE,mBAAmB,CAAA;CAC3B,GAAG,oBAAoB,GAAG,KAAK,CAiE/B;AAyCD,qEAAqE;AACrE,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAEpF;AAED,iFAAiF;AACjF,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAElF;AAED,MAAM,WAAW,gCAAgC;IAC/C,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,qBAAqB,EAAE,MAAM,CAAA;IAC7B,4BAA4B,EAAE,4BAA4B,CAAA;CAC3D;AAED,MAAM,WAAW,yCAAyC;IACxD,GAAG,EAAE,MAAM,CAAA;IACX,eAAe,EAAE,MAAM,CAAA;IACvB,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;IACnB,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,eAAe,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IACtC,YAAY,CAAC,EAAE,UAAU,CAAA;IACzB,kBAAkB,EAAE,MAAM,EAAE,EAAE,CAAA;IAC9B,gCAAgC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAChD,sBAAsB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAA;IACxC,iBAAiB,CAAC,EAAE,iBAAiB,CAAA;IACrC,gBAAgB,CAAC,EAAE,iBAAiB,CAAA;IACpC,yBAAyB,EAAE,uBAAuB,CAAA;IAClD,iFAAiF;IACjF,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,4EAA4E;IAC5E,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,QAAQ,EAAE,gCAAgC,CAAA;CAC3C;AAED,MAAM,WAAW,wCAAwC;IACvD,iBAAiB,EAAE,uBAAuB,CAAA;IAC1C,oBAAoB,EAAE,4BAA4B,CAAA;IAClD,eAAe,EAAE,aAAa,GAAG,IAAI,CAAA;IACrC,kBAAkB,EAAE,yBAAyB,GAAG,IAAI,CAAA;CACrD;AAmCD;;;;GAIG;AACH,wBAAgB,uCAAuC,CACrD,OAAO,EAAE,yCAAyC,GACjD,wCAAwC,GAAG,KAAK,CA4KlD;AAED,MAAM,WAAW,iDAAiD;IAChE,GAAG,EAAE,MAAM,CAAA;IACX,QAAQ,EAAE,MAAM,CAAA;IAChB,yBAAyB,EAAE,uBAAuB,CAAA;IAClD,4BAA4B,EAAE,4BAA4B,CAAA;IAC1D,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED;;;GAGG;AACH,wBAAgB,0CAA0C,CACxD,OAAO,EAAE,iDAAiD,GACzD,OAAO,CAiDT;AAED,MAAM,WAAW,iDAAiD;IAChE,GAAG,EAAE,MAAM,CAAA;IACX,QAAQ,EAAE,MAAM,CAAA;IAChB,yBAAyB,EAAE,uBAAuB,CAAA;IAClD,4BAA4B,EAAE,4BAA4B,CAAA;IAC1D,eAAe,EAAE,aAAa,GAAG,IAAI,CAAA;IACrC,kBAAkB,EAAE,yBAAyB,GAAG,IAAI,CAAA;IACpD,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED,MAAM,WAAW,gDAAgD;IAC/D,iBAAiB,EAAE,uBAAuB,CAAA;IAC1C,oBAAoB,EAAE,4BAA4B,CAAA;IAClD,eAAe,EAAE,aAAa,GAAG,IAAI,CAAA;IACrC,kBAAkB,EAAE,yBAAyB,GAAG,IAAI,CAAA;CACrD;AAED,mFAAmF;AACnF,wBAAgB,0CAA0C,CACxD,OAAO,EAAE,iDAAiD,GACzD,gDAAgD,GAAG,KAAK,CAwE1D;AASD;mFACmF;AACnF,wBAAgB,6BAA6B,CAC3C,GAAG,EAAE,MAAM,EACX,uBAAuB,EAAE,MAAM,EAC/B,OAAO,EAAE,iBAAiB,EAC1B,kBAAkB,CAAC,EAAE,uBAAuB,GAC3C,uBAAuB,GAAG,KAAK,CA6BjC;AAED;;;yDAGyD;AACzD,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,MAAM,EACX,kBAAkB,CAAC,EAAE,uBAAuB,GAC3C,OAAO,CAgBT;AAED;;6DAE6D;AAC7D,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG;IAClD,eAAe,EAAE,MAAM,CAAA;IACvB,uBAAuB,CAAC,EAAE,MAAM,CAAA;IAChC,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;CACrB,GAAG,SAAS,CAWZ;AAED;uEACuE;AACvE,wBAAgB,kBAAkB,IAAI,KAAK,CAAC;IAC1C,GAAG,EAAE,MAAM,CAAA;IACX,eAAe,EAAE,MAAM,CAAA;IACvB,uBAAuB,CAAC,EAAE,MAAM,CAAA;IAChC,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;CACrB,CAAC,CAUD;AAED,wBAAgB,mBAAmB,IAAI,IAAI,CAmB1C"}
|
package/dist/proxy/settings.d.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*
|
|
8
8
|
* This is a leaf module — no imports from server.ts or session/.
|
|
9
9
|
*/
|
|
10
|
+
import type { PriorityFailbackPolicy } from "./routing";
|
|
10
11
|
export interface MeridianSettings {
|
|
11
12
|
/** Last active profile ID — restored on proxy startup */
|
|
12
13
|
activeProfile?: string;
|
|
@@ -16,6 +17,7 @@ export interface MeridianSettings {
|
|
|
16
17
|
/** Priority-mode pool order (highest priority first). Falls back to
|
|
17
18
|
* profiles.json order. MERIDIAN_PROFILE_ORDER env var takes precedence. */
|
|
18
19
|
profileOrder?: string[];
|
|
20
|
+
priorityFailback?: PriorityFailbackPolicy;
|
|
19
21
|
}
|
|
20
22
|
/** Read settings from disk. Returns empty object if file doesn't exist or is invalid. */
|
|
21
23
|
export declare function loadSettings(): MeridianSettings;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/proxy/settings.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;
|
|
1
|
+
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/proxy/settings.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAA;AAqBvD,MAAM,WAAW,gBAAgB;IAC/B,yDAAyD;IACzD,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;8EAC0E;IAC1E,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;gFAC4E;IAC5E,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB,gBAAgB,CAAC,EAAE,sBAAsB,CAAA;CAC1C;AAED,yFAAyF;AACzF,wBAAgB,YAAY,IAAI,gBAAgB,CAQ/C;AAED,4FAA4F;AAC5F,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAUrE;AAED,iCAAiC;AACjC,wBAAgB,UAAU,CAAC,CAAC,SAAS,MAAM,gBAAgB,EAAE,GAAG,EAAE,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAExF;AAED,6CAA6C;AAC7C,wBAAgB,UAAU,CAAC,CAAC,SAAS,MAAM,gBAAgB,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,IAAI,CAErG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/proxy/setup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/proxy/setup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAWH;;;;GAIG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;aACnB,UAAU,EAAE,MAAM;gBAAlB,UAAU,EAAE,MAAM;CAI/C;AAED,qBAAa,oBAAqB,SAAQ,KAAK;aACjB,YAAY,EAAE,MAAM;gBAApB,YAAY,EAAE,MAAM;CAIjD;AAED,qBAAa,4BAA6B,SAAQ,KAAK;aAEnC,UAAU,EAAE,MAAM;aAClB,WAAW,EAAE,MAAM;gBADnB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM;CAKtC;AA+BD,wBAAgB,sBAAsB,IAAI,MAAM,CAK/C;AASD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGtD;AAED,MAAM,MAAM,kBAAkB,GAAG,IAAI,GAAG,IAAI,CAAA;AAE5C,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,kBAAkB,CAAA;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,eAAO,MAAM,6BAA6B,qBAAqB,CAAA;AAE/D,6EAA6E;AAC7E,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAgBxD;AAED,wEAAwE;AACxE,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS,CAYrF;AAED,KAAK,YAAY,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAA;AAE3D;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,GAAE,SAAS,MAAM,EAEI,EAC7B,KAAK,GAAE,YASN,GACA,iBAAiB,CAQnB;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,kBAAkB,GAAG,MAAM,CAE/F;AA4BD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,kBAAkB,CAAC,EAAE,MAAM,GAAG,OAAO,CAgB/F;AAaD,sDAAsD;AACtD,wBAAgB,uBAAuB,IAAI,IAAI,CAE9C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,6BAA6B,CAAC,KAAK,EAAE;IACnD,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;IAC7B,mEAAmE;IACnE,eAAe,EAAE,MAAM,GAAG,SAAS,CAAA;IACnC,mEAAmE;IACnE,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;CAC9B,GAAG,MAAM,GAAG,SAAS,CAkBrB;AAMD,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,iBAAiB,EAAE,OAAO,CAAA;IAC1B,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,OAAO,EAAE,OAAO,CAAA;CACjB;AAED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CACtB,UAAU,EAAE,MAAM,EAClB,UAAU,CAAC,EAAE,MAAM,EACnB,UAAU,GAAE,kBAAyB,GACpC,WAAW,CAiFb"}
|
package/dist/server.js
CHANGED
|
@@ -11,14 +11,14 @@ import {
|
|
|
11
11
|
runObserveHook,
|
|
12
12
|
runTransformHook,
|
|
13
13
|
startProxyServer
|
|
14
|
-
} from "./cli-
|
|
15
|
-
import"./cli-
|
|
14
|
+
} from "./cli-7cts44b5.js";
|
|
15
|
+
import"./cli-pdpry6q0.js";
|
|
16
16
|
import"./cli-sry5aqdj.js";
|
|
17
17
|
import"./cli-8yp89fan.js";
|
|
18
18
|
import"./cli-0ed6j0vk.js";
|
|
19
19
|
import"./cli-khhjyk04.js";
|
|
20
20
|
import"./cli-vj9cv18n.js";
|
|
21
|
-
import"./cli-
|
|
21
|
+
import"./cli-n8t34zmq.js";
|
|
22
22
|
import"./cli-p9swy5t3.js";
|
|
23
23
|
export {
|
|
24
24
|
startProxyServer,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rynfar/meridian",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.65.0",
|
|
4
4
|
"description": "Local Anthropic API powered by your Claude Max subscription. One subscription, every agent.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/server.js",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"postbuild": "node scripts/fix-bun-exports.mjs && node --check dist/cli.js && node --check dist/server.js && node --check dist/meridian-v2.js && node -e \"if(!require('fs').existsSync('dist/proxy/server.d.ts'))process.exit(1)\"",
|
|
26
26
|
"postinstall": "node -e \"try{require('child_process').spawnSync(process.execPath,[require.resolve('@anthropic-ai/claude-code/install.cjs')],{stdio:'inherit'})}catch(e){console.error('[meridian] claude-code postinstall skipped:',e.message)}\"",
|
|
27
27
|
"prepublishOnly": "bun run build",
|
|
28
|
-
"test": "bun test --path-ignore-patterns '**/*session-store*' --path-ignore-patterns '**/*proxy-async-ops*' --path-ignore-patterns '**/*models-auth-status*' --path-ignore-patterns '**/*proxy-context-usage-store*' --path-ignore-patterns '**/*proxy-passthrough-thinking*' --path-ignore-patterns '**/*proxy-thinking-setting*' --path-ignore-patterns '**/*session-recovery*' --path-ignore-patterns '**/*models.test*' --path-ignore-patterns '**/*proxy-health-build*' && bun test src/__tests__/proxy-async-ops.test.ts && bun test src/__tests__/proxy-session-store.test.ts && bun test src/__tests__/session-store-pruning.test.ts && bun test src/__tests__/proxy-session-store-locking.test.ts && bun test src/__tests__/proxy-context-usage-store.test.ts && bun test src/__tests__/models-auth-status.test.ts && bun test src/__tests__/proxy-passthrough-thinking.test.ts && bun test src/__tests__/proxy-session-recovery.test.ts && bun test src/__tests__/proxy-thinking-setting.test.ts && bun test src/__tests__/models.test.ts && bun test src/__tests__/proxy-health-build.test.ts",
|
|
28
|
+
"test": "bun test --path-ignore-patterns '**/*session-store*' --path-ignore-patterns '**/*priority-routing-integration*' --path-ignore-patterns '**/*proxy-async-ops*' --path-ignore-patterns '**/*models-auth-status*' --path-ignore-patterns '**/*proxy-context-usage-store*' --path-ignore-patterns '**/*proxy-passthrough-thinking*' --path-ignore-patterns '**/*proxy-thinking-setting*' --path-ignore-patterns '**/*session-recovery*' --path-ignore-patterns '**/*models.test*' --path-ignore-patterns '**/*proxy-health-build*' && bun test src/__tests__/proxy-async-ops.test.ts && bun test src/__tests__/proxy-session-store.test.ts && bun test src/__tests__/session-store-pruning.test.ts && bun test src/__tests__/proxy-session-store-locking.test.ts && bun test src/__tests__/proxy-context-usage-store.test.ts && bun test src/__tests__/models-auth-status.test.ts && bun test src/__tests__/proxy-passthrough-thinking.test.ts && bun test src/__tests__/proxy-session-recovery.test.ts && bun test src/__tests__/proxy-thinking-setting.test.ts && bun test src/__tests__/models.test.ts && bun test src/__tests__/proxy-health-build.test.ts && bun test src/__tests__/priority-routing-integration.test.ts",
|
|
29
29
|
"nix:lock": "bun2nix -o bun.nix",
|
|
30
30
|
"typecheck": "tsc --noEmit",
|
|
31
31
|
"proxy:direct": "bun run ./bin/cli.ts"
|
package/plugin/meridian-v2.ts
CHANGED
|
@@ -16,6 +16,14 @@
|
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
import * as Plugin from "@opencode-ai/plugin/promise/plugin"
|
|
19
|
+
import {
|
|
20
|
+
PRIORITY_ATTESTATION_HEADER,
|
|
21
|
+
createPriorityAttestation,
|
|
22
|
+
deleteHeader,
|
|
23
|
+
getHeader,
|
|
24
|
+
setHeader,
|
|
25
|
+
type MutableHeaders,
|
|
26
|
+
} from "./priority-attestation"
|
|
19
27
|
|
|
20
28
|
/** Exact V2 host used to compile and validate this beta-only integration. */
|
|
21
29
|
export const SUPPORTED_OPENCODE_V2_VERSION = "0.0.0-beta-18314"
|
|
@@ -35,6 +43,7 @@ const MERIDIAN_CONTROL_HEADERS = [
|
|
|
35
43
|
"x-meridian-source",
|
|
36
44
|
"x-opencode-agent-name",
|
|
37
45
|
"x-opencode-agent-mode",
|
|
46
|
+
PRIORITY_ATTESTATION_HEADER,
|
|
38
47
|
] as const
|
|
39
48
|
|
|
40
49
|
export interface AgentTraits {
|
|
@@ -57,25 +66,6 @@ export function fallbackAgentTraits(agent: string): AgentTraits {
|
|
|
57
66
|
return BUILTIN_AGENT_TRAITS[agent] ?? { mode: "primary", hidden: false }
|
|
58
67
|
}
|
|
59
68
|
|
|
60
|
-
type MutableHeaders = Record<string, string> | Headers
|
|
61
|
-
|
|
62
|
-
function deleteHeader(headers: MutableHeaders, name: string): void {
|
|
63
|
-
if (headers instanceof Headers) {
|
|
64
|
-
headers.delete(name)
|
|
65
|
-
return
|
|
66
|
-
}
|
|
67
|
-
const lower = name.toLowerCase()
|
|
68
|
-
for (const key of Object.keys(headers)) {
|
|
69
|
-
if (key.toLowerCase() === lower) delete headers[key]
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function setHeader(headers: MutableHeaders, name: string, value: string): void {
|
|
74
|
-
deleteHeader(headers, name)
|
|
75
|
-
if (headers instanceof Headers) headers.set(name, value)
|
|
76
|
-
else headers[name] = value
|
|
77
|
-
}
|
|
78
|
-
|
|
79
69
|
function safeAgentName(agent: string): string {
|
|
80
70
|
return agent.replace(/[^\x20-\x7E]/g, "").trim() || "unknown"
|
|
81
71
|
}
|
|
@@ -123,55 +113,210 @@ export function applyMeridianV2Headers(
|
|
|
123
113
|
setHeader(headers, "x-opencode-agent-mode", internalMode)
|
|
124
114
|
}
|
|
125
115
|
|
|
116
|
+
const INTERNAL_ROUTING_AGENT_IDS = new Set(["title", "summary", "compaction"])
|
|
117
|
+
const AGENT_CACHE_MAX = 256
|
|
118
|
+
const AGENT_CACHE_TTL_MS = 5_000
|
|
119
|
+
const LOOKUP_TIMEOUT_MS = 250
|
|
120
|
+
const MAX_CONTEXT_ENTRIES = 2_048
|
|
121
|
+
const SAFE_ID_PATTERN = /^[A-Za-z0-9._:-]{1,128}$/
|
|
122
|
+
|
|
123
|
+
type ExactAgentMode = "primary" | "subagent" | "all"
|
|
124
|
+
type ResolvedAgentMetadata = {
|
|
125
|
+
readonly traits: AgentTraits
|
|
126
|
+
readonly exactMode: ExactAgentMode | undefined
|
|
127
|
+
readonly authoritative: boolean
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
131
|
+
return typeof value === "object" && value !== null && !Array.isArray(value)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async function withTimeout<T>(pending: Promise<T>, timeoutMs: number): Promise<T | undefined> {
|
|
135
|
+
let timer: ReturnType<typeof setTimeout> | undefined
|
|
136
|
+
const timedOut = new Promise<undefined>((resolve) => {
|
|
137
|
+
timer = setTimeout(() => resolve(undefined), timeoutMs)
|
|
138
|
+
timer.unref?.()
|
|
139
|
+
})
|
|
140
|
+
try {
|
|
141
|
+
return await Promise.race([pending, timedOut])
|
|
142
|
+
} finally {
|
|
143
|
+
if (timer) clearTimeout(timer)
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function isRootV2Session(value: unknown, sessionID: string): boolean {
|
|
148
|
+
return isRecord(value)
|
|
149
|
+
&& value.id === sessionID
|
|
150
|
+
&& value.parentID === undefined
|
|
151
|
+
&& value.fork === undefined
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Find the exact host message ID that initiated the active model loop.
|
|
156
|
+
* Assistant/tool steps and selection records belong to the current loop and
|
|
157
|
+
* are skipped. A synthetic/compaction/shell/skill/system or unknown initiator
|
|
158
|
+
* fails closed instead of reusing an older human ID.
|
|
159
|
+
*/
|
|
160
|
+
type V2HumanTurn = { readonly id: string; readonly issuedAt: number }
|
|
161
|
+
|
|
162
|
+
export function findLatestV2HumanTurn(value: unknown): V2HumanTurn | undefined {
|
|
163
|
+
if (!Array.isArray(value) || value.length === 0 || value.length > MAX_CONTEXT_ENTRIES) return undefined
|
|
164
|
+
for (let index = value.length - 1; index >= 0; index -= 1) {
|
|
165
|
+
const message = value[index]
|
|
166
|
+
if (!isRecord(message) || typeof message.type !== "string") return undefined
|
|
167
|
+
if (
|
|
168
|
+
message.type === "assistant"
|
|
169
|
+
|| message.type === "agent-switched"
|
|
170
|
+
|| message.type === "model-switched"
|
|
171
|
+
|| message.type === "location-switched"
|
|
172
|
+
) {
|
|
173
|
+
continue
|
|
174
|
+
}
|
|
175
|
+
if (message.type !== "user" || typeof message.id !== "string" || !SAFE_ID_PATTERN.test(message.id)) {
|
|
176
|
+
return undefined
|
|
177
|
+
}
|
|
178
|
+
const time = isRecord(message.time) ? message.time : undefined
|
|
179
|
+
const createdAt = time?.created
|
|
180
|
+
if (typeof createdAt !== "number" || !Number.isSafeInteger(createdAt) || createdAt < 0) return undefined
|
|
181
|
+
return { id: message.id, issuedAt: Math.floor(createdAt / 1000) }
|
|
182
|
+
}
|
|
183
|
+
return undefined
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export function findLatestV2HumanMessageId(value: unknown): string | undefined {
|
|
187
|
+
return findLatestV2HumanTurn(value)?.id
|
|
188
|
+
}
|
|
189
|
+
|
|
126
190
|
const MeridianV2Plugin = Plugin.define({
|
|
127
191
|
id: "meridian",
|
|
128
192
|
setup: async (context) => {
|
|
129
193
|
const traitsByAgent = new Map<string, {
|
|
130
194
|
expiresAt: number
|
|
131
|
-
|
|
195
|
+
request: symbol
|
|
196
|
+
pending: Promise<ResolvedAgentMetadata>
|
|
132
197
|
}>()
|
|
133
198
|
const registered: Array<{ dispose: () => Promise<void> }> = []
|
|
134
199
|
|
|
135
|
-
const resolveAgentTraits = (agent: string): Promise<
|
|
200
|
+
const resolveAgentTraits = (agent: string, refresh = false): Promise<ResolvedAgentMetadata> => {
|
|
136
201
|
const cached = traitsByAgent.get(agent)
|
|
137
|
-
if (cached && cached.expiresAt > Date.now()) return cached.pending
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
202
|
+
if (!refresh && cached && cached.expiresAt > Date.now()) return cached.pending
|
|
203
|
+
if (refresh) traitsByAgent.delete(agent)
|
|
204
|
+
|
|
205
|
+
const request = Symbol(agent)
|
|
206
|
+
const pending = (async (): Promise<ResolvedAgentMetadata> => {
|
|
207
|
+
const controller = new AbortController()
|
|
208
|
+
try {
|
|
209
|
+
const result = await withTimeout(
|
|
210
|
+
context.agent.get({ agentID: agent }, { signal: controller.signal }),
|
|
211
|
+
LOOKUP_TIMEOUT_MS,
|
|
212
|
+
)
|
|
213
|
+
const data = result?.data
|
|
214
|
+
if (
|
|
215
|
+
!data
|
|
216
|
+
|| (data.mode !== "primary" && data.mode !== "subagent" && data.mode !== "all")
|
|
217
|
+
|| typeof data.hidden !== "boolean"
|
|
218
|
+
) {
|
|
219
|
+
if (traitsByAgent.get(agent)?.request === request) traitsByAgent.delete(agent)
|
|
220
|
+
return { traits: fallbackAgentTraits(agent), exactMode: undefined, authoritative: false }
|
|
221
|
+
}
|
|
222
|
+
return {
|
|
223
|
+
traits: {
|
|
224
|
+
mode: data.mode === "subagent" ? "subagent" : "primary",
|
|
225
|
+
hidden: data.hidden,
|
|
226
|
+
},
|
|
227
|
+
exactMode: data.mode,
|
|
228
|
+
authoritative: true,
|
|
229
|
+
}
|
|
230
|
+
} catch {
|
|
231
|
+
// Retry a transient failure at the final HTTP boundary or next turn.
|
|
232
|
+
if (traitsByAgent.get(agent)?.request === request) traitsByAgent.delete(agent)
|
|
233
|
+
return { traits: fallbackAgentTraits(agent), exactMode: undefined, authoritative: false }
|
|
234
|
+
} finally {
|
|
235
|
+
controller.abort()
|
|
236
|
+
}
|
|
237
|
+
})()
|
|
238
|
+
traitsByAgent.delete(agent)
|
|
239
|
+
traitsByAgent.set(agent, { request, expiresAt: Date.now() + AGENT_CACHE_TTL_MS, pending })
|
|
240
|
+
while (traitsByAgent.size > AGENT_CACHE_MAX) {
|
|
241
|
+
const oldest = traitsByAgent.keys().next().value
|
|
242
|
+
if (oldest === undefined) break
|
|
243
|
+
traitsByAgent.delete(oldest)
|
|
244
|
+
}
|
|
152
245
|
return pending
|
|
153
246
|
}
|
|
154
247
|
|
|
155
248
|
const apply = async (
|
|
156
249
|
input: { sessionID: string; agent: string; model: { providerID: string } },
|
|
157
250
|
headers: MutableHeaders,
|
|
158
|
-
|
|
159
|
-
|
|
251
|
+
refreshTraits = false,
|
|
252
|
+
): Promise<ResolvedAgentMetadata | undefined> => {
|
|
253
|
+
if (!MERIDIAN_PROVIDERS.has(String(input.model.providerID))) return undefined
|
|
160
254
|
const agent = String(input.agent)
|
|
255
|
+
const metadata = await resolveAgentTraits(agent, refreshTraits)
|
|
161
256
|
applyMeridianV2Headers(headers, {
|
|
162
257
|
sessionID: String(input.sessionID),
|
|
163
258
|
agent,
|
|
164
|
-
traits:
|
|
259
|
+
traits: metadata.traits,
|
|
165
260
|
})
|
|
261
|
+
return metadata
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const resolveHumanTurn = async (
|
|
265
|
+
input: { sessionID: string; agent: string },
|
|
266
|
+
headers: MutableHeaders,
|
|
267
|
+
metadata: ResolvedAgentMetadata,
|
|
268
|
+
): Promise<V2HumanTurn | undefined> => {
|
|
269
|
+
const sessionID = String(input.sessionID)
|
|
270
|
+
const agent = String(input.agent)
|
|
271
|
+
if (
|
|
272
|
+
!metadata.authoritative
|
|
273
|
+
|| metadata.exactMode !== "primary"
|
|
274
|
+
|| metadata.traits.hidden
|
|
275
|
+
|| INTERNAL_ROUTING_AGENT_IDS.has(agent)
|
|
276
|
+
|| safeAgentName(agent) !== agent
|
|
277
|
+
|| getHeader(headers, "x-meridian-profile") !== undefined
|
|
278
|
+
) {
|
|
279
|
+
return undefined
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const controller = new AbortController()
|
|
283
|
+
try {
|
|
284
|
+
const result = await withTimeout(Promise.all([
|
|
285
|
+
context.session.get({ sessionID }, { signal: controller.signal }),
|
|
286
|
+
context.session.context({ sessionID }, { signal: controller.signal }),
|
|
287
|
+
]), LOOKUP_TIMEOUT_MS)
|
|
288
|
+
if (!result || !isRootV2Session(result[0], sessionID)) return undefined
|
|
289
|
+
return findLatestV2HumanTurn(result[1])
|
|
290
|
+
} catch {
|
|
291
|
+
return undefined
|
|
292
|
+
} finally {
|
|
293
|
+
controller.abort()
|
|
294
|
+
}
|
|
166
295
|
}
|
|
167
296
|
|
|
168
297
|
try {
|
|
169
298
|
for (const providerID of MERIDIAN_PROVIDERS) {
|
|
170
299
|
registered.push(await context.session.hook("model.request", async (input) => {
|
|
300
|
+
// Apply lineage/tier identity early, but never emit the routing
|
|
301
|
+
// attestation before the final HTTP boundary.
|
|
171
302
|
await apply(input, input.headers)
|
|
172
303
|
}, { providerID }))
|
|
173
304
|
registered.push(await context.session.hook("http.request", async (input) => {
|
|
174
|
-
|
|
305
|
+
// Re-read exact visibility/mode at the final boundary. The model-hook
|
|
306
|
+
// cache is capability-only and must never authorize a stale visible
|
|
307
|
+
// primary after a config reload.
|
|
308
|
+
const metadata = await apply(input, input.request.headers, true)
|
|
309
|
+
if (!metadata) return
|
|
310
|
+
const humanTurn = await resolveHumanTurn(input, input.request.headers, metadata)
|
|
311
|
+
if (!humanTurn) return
|
|
312
|
+
const token = createPriorityAttestation({
|
|
313
|
+
generation: "oc2b18314",
|
|
314
|
+
sessionId: String(input.sessionID),
|
|
315
|
+
agentId: String(input.agent),
|
|
316
|
+
humanMessageId: humanTurn.id,
|
|
317
|
+
issuedAt: humanTurn.issuedAt,
|
|
318
|
+
})
|
|
319
|
+
if (token) setHeader(input.request.headers, PRIORITY_ATTESTATION_HEADER, token)
|
|
175
320
|
}, { providerID }))
|
|
176
321
|
}
|
|
177
322
|
} catch (error) {
|