narraeon 0.7.10 → 0.8.1
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/node/protocol/modelConnections.js +15 -0
- package/dist/node/protocol/modelUsage.js +4 -0
- package/dist/node/protocol/sillyTavernContent.js +1 -0
- package/dist/node/protocol/v1.js +97 -0
- package/dist/node/runtime/V1Runtime.js +105 -3
- package/dist/node/runtime/authoring/AuthoringEditPlan.js +79 -0
- package/dist/node/runtime/authoring/AuthoringRequestSnapshot.js +15 -3
- package/dist/node/runtime/authoring/AuthoringRetry.js +59 -0
- package/dist/node/runtime/authoring/DamagedGoogleContinuation.js +68 -0
- package/dist/node/runtime/authoring/ModelToolConversation.js +66 -25
- package/dist/node/runtime/content/ContentWorkspace.js +10 -2
- package/dist/node/runtime/content/CurrentTreeContentLibrary.js +14 -8
- package/dist/node/runtime/content/SillyTavernContent.js +796 -0
- package/dist/node/runtime/model/AiFailureLog.js +8 -1
- package/dist/node/runtime/model/DispatchFailure.js +8 -0
- package/dist/node/runtime/model/FileNativeModelAdapters.js +627 -18
- package/dist/node/runtime/model/GoogleHopJournal.js +90 -0
- package/dist/node/runtime/model/GoogleInteractionsStream.js +242 -0
- package/dist/node/runtime/model/GoogleRequestPreview.js +184 -0
- package/dist/node/runtime/model/ModelConnectionStore.js +4 -1
- package/dist/node/runtime/model/ProviderExchangeState.js +44 -1
- package/dist/node/runtime/model/ProviderStream.js +4 -2
- package/dist/node/runtime/play/FileNativePlayAdvanceStore.js +4 -4
- package/dist/node/runtime/play/FileNativePlayPresetStore.js +150 -78
- package/dist/node/runtime/play/FileNativePlayTimelineStore.js +199 -10
- package/dist/node/runtime/play/OrderedPlayPrompts.js +139 -178
- package/dist/node/runtime/play/PlayAdvanceLifecycle.js +51 -23
- package/dist/node/runtime/play/PlayCallChain.js +92 -8
- package/dist/node/runtime/play/PlayFollowupRequests.js +23 -3
- package/dist/node/runtime/prompt/PromptCompilationCodec.js +2 -1
- package/dist/node/runtime/setting/FileNativeSettingImprovementStore.js +321 -15
- package/dist/node/runtime/setting/SettingImprovementSession.js +285 -21
- package/dist/node/runtime/world-revision/FileNativeWorldRevisionStore.js +236 -15
- package/dist/node/runtime/world-revision/WorldRevisionSession.js +324 -50
- package/dist/node/runtime/world-revision/WorldRevisionWorkspace.js +47 -1
- package/dist/node/shared/application-preset-files.js +29 -0
- package/dist/node/shared/default-preset-host.js +50 -38
- package/dist/node/shared/first-party-action-choices.js +7 -11
- package/dist/node/shared/first-party-generic-panels.js +7 -11
- package/dist/node/shared/first-party-player-view.js +7 -11
- package/dist/node/shared/ordered-author-prompts.js +6 -4
- package/dist/node/shared/ordered-play-prompts.js +4 -2
- package/dist/node/shared/prompt-arrangement.js +205 -0
- package/dist/node/shared/sillytavern-preset.js +454 -0
- package/dist/web/assets/index-BthiDIQu.js +1432 -0
- package/dist/web/assets/{index-DH2BVsYd.css → index-wO9Y4HT1.css} +1 -1
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/dist/web/assets/index-B2kbaOGe.js +0 -1408
|
@@ -3,9 +3,12 @@ import { upgradeLegacyEpochs } from "./LegacyWorldRevisionEpochUpgrade.js";
|
|
|
3
3
|
import { isPackageFollowupControlPath } from "../content/PackageFollowups.js";
|
|
4
4
|
import { validAuthoringRequests, } from "../authoring/AuthoringRequestSnapshot.js";
|
|
5
5
|
import { createHash, randomUUID } from "node:crypto";
|
|
6
|
-
import {
|
|
6
|
+
import { readGoogleHops, writeGoogleHop } from "../model/GoogleHopJournal.js";
|
|
7
|
+
import { link, mkdir, open, readFile, readdir, rename, rm, stat, } from "node:fs/promises";
|
|
7
8
|
import { dirname, join, resolve } from "node:path";
|
|
8
9
|
import { gameplayPath } from "../../protocol/gameplay.js";
|
|
10
|
+
import { validGoogleInteractionsSteps } from "../model/ProviderExchangeState.js";
|
|
11
|
+
import { hasDamagedGoogleSteps, withoutDamagedGoogleSteps, } from "../authoring/DamagedGoogleContinuation.js";
|
|
9
12
|
import { contentTreeFingerprint } from "../content/ContentTreeFingerprint.js";
|
|
10
13
|
import { isPlayPresetBinding, } from "../play/FileNativePlayPresetStore.js";
|
|
11
14
|
const uuidV4Pattern = "[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}";
|
|
@@ -40,12 +43,19 @@ export class FileNativeWorldRevisionStore {
|
|
|
40
43
|
this.#epochsRoot = join(root, "epochs");
|
|
41
44
|
this.#sessionsRoot = join(root, "sessions");
|
|
42
45
|
}
|
|
46
|
+
get sessionScope() {
|
|
47
|
+
return this.#sessionsRoot;
|
|
48
|
+
}
|
|
43
49
|
createEpochId() {
|
|
44
50
|
return `revision-${randomUUID()}`;
|
|
45
51
|
}
|
|
46
52
|
createSessionId() {
|
|
47
53
|
return `world-session-${randomUUID()}`;
|
|
48
54
|
}
|
|
55
|
+
recordGoogleHop(sessionId, requestId, hop) {
|
|
56
|
+
assertSessionId(sessionId);
|
|
57
|
+
return writeGoogleHop(join(this.#sessionsRoot, ".google-hops", sessionId), requestId, hop, () => stat(this.#sessionPath(sessionId)).then(() => true, () => false));
|
|
58
|
+
}
|
|
49
59
|
createChangeSetId() {
|
|
50
60
|
return `change-set:${randomUUID()}`;
|
|
51
61
|
}
|
|
@@ -89,14 +99,108 @@ export class FileNativeWorldRevisionStore {
|
|
|
89
99
|
});
|
|
90
100
|
}
|
|
91
101
|
readSession(sessionId) {
|
|
92
|
-
return this.#afterMutations(() =>
|
|
102
|
+
return this.#afterMutations(async () => {
|
|
103
|
+
try {
|
|
104
|
+
const session = await this.#readSession(sessionId);
|
|
105
|
+
if (hasDamagedGoogleSteps(session) &&
|
|
106
|
+
(await this.#damagedSession(sessionId)))
|
|
107
|
+
throw new Error("The historical conversation has damaged Google continuation; start a fresh model context");
|
|
108
|
+
return session;
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
if (await this.#damagedSession(sessionId))
|
|
112
|
+
throw new Error("The historical conversation has damaged Google continuation; start a fresh model context", { cause: error });
|
|
113
|
+
throw error;
|
|
114
|
+
}
|
|
115
|
+
});
|
|
93
116
|
}
|
|
94
117
|
saveSession(session) {
|
|
95
118
|
return this.#mutate(async () => {
|
|
96
119
|
validateSession(session);
|
|
97
|
-
|
|
120
|
+
const path = this.#sessionPath(session.sessionId);
|
|
121
|
+
{
|
|
122
|
+
const source = await readFile(path).catch((error) => {
|
|
123
|
+
if (isNodeError(error) && error.code === "ENOENT")
|
|
124
|
+
return null;
|
|
125
|
+
throw error;
|
|
126
|
+
});
|
|
127
|
+
if (source !== null) {
|
|
128
|
+
const old = validateSession(JSON.parse(source.toString("utf8")));
|
|
129
|
+
if (old.schemaVersion === 3 && session.schemaVersion !== 3)
|
|
130
|
+
throw new Error("Cannot downgrade a migrated world-revision session");
|
|
131
|
+
if (old.schemaVersion !== 3) {
|
|
132
|
+
const backup = join(this.#sessionsRoot, ".legacy", `${session.sessionId}.json`);
|
|
133
|
+
await mkdir(dirname(backup), { recursive: true, mode: 0o700 });
|
|
134
|
+
const temporary = `${backup}.${randomUUID()}.tmp`;
|
|
135
|
+
try {
|
|
136
|
+
const handle = await open(temporary, "wx", 0o600);
|
|
137
|
+
try {
|
|
138
|
+
await handle.writeFile(source);
|
|
139
|
+
}
|
|
140
|
+
finally {
|
|
141
|
+
await handle.close();
|
|
142
|
+
}
|
|
143
|
+
try {
|
|
144
|
+
await link(temporary, backup);
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
if (!isNodeError(error) || error.code !== "EEXIST")
|
|
148
|
+
throw error;
|
|
149
|
+
}
|
|
150
|
+
if (!(await readFile(backup)).equals(source))
|
|
151
|
+
throw new Error("World-revision legacy source backup does not match the original bytes");
|
|
152
|
+
}
|
|
153
|
+
finally {
|
|
154
|
+
await rm(temporary, { force: true });
|
|
155
|
+
}
|
|
156
|
+
session.schemaVersion = 3;
|
|
157
|
+
validateSession(session);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
await publishJson(path, session);
|
|
98
162
|
});
|
|
99
163
|
}
|
|
164
|
+
async prepareEdit(input) {
|
|
165
|
+
validateEpoch(input.epoch);
|
|
166
|
+
validateSession(input.session);
|
|
167
|
+
if (input.epoch.worldId !== input.session.worldId ||
|
|
168
|
+
input.epoch.epochId !== input.session.epochId ||
|
|
169
|
+
!treeRevisionPattern.test(input.beforeRevision))
|
|
170
|
+
throw new Error("Invalid world-revision edit intent");
|
|
171
|
+
await publishJson(this.#editPath(input.epoch.epochId), input);
|
|
172
|
+
}
|
|
173
|
+
async readEdit(epochId) {
|
|
174
|
+
let value;
|
|
175
|
+
try {
|
|
176
|
+
value = JSON.parse(await readFile(this.#editPath(epochId), "utf8"));
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
if (isNodeError(error) && error.code === "ENOENT")
|
|
180
|
+
return null;
|
|
181
|
+
throw error;
|
|
182
|
+
}
|
|
183
|
+
if (!isRecord(value) ||
|
|
184
|
+
!hasExactKeys(value, ["beforeRevision", "epoch", "session"]) ||
|
|
185
|
+
typeof value.beforeRevision !== "string" ||
|
|
186
|
+
!treeRevisionPattern.test(value.beforeRevision))
|
|
187
|
+
throw new Error("Invalid world-revision edit intent");
|
|
188
|
+
const epoch = validateEpoch(value.epoch);
|
|
189
|
+
const session = validateSession(value.session);
|
|
190
|
+
if (epoch.epochId !== epochId ||
|
|
191
|
+
epoch.worldId !== session.worldId ||
|
|
192
|
+
epoch.epochId !== session.epochId ||
|
|
193
|
+
epoch.lifecycle !== "active")
|
|
194
|
+
throw new Error("Invalid world-revision edit identity");
|
|
195
|
+
return { beforeRevision: value.beforeRevision, epoch, session };
|
|
196
|
+
}
|
|
197
|
+
async removeEdit(epochId) {
|
|
198
|
+
await rm(this.#editPath(epochId), { force: true });
|
|
199
|
+
}
|
|
200
|
+
#editPath(epochId) {
|
|
201
|
+
assertEpochId(epochId);
|
|
202
|
+
return join(this.#epochsRoot, `.edit-${epochId}.json`);
|
|
203
|
+
}
|
|
100
204
|
async listSessions(worldId) {
|
|
101
205
|
return this.#afterMutations(async () => {
|
|
102
206
|
const entries = await readdir(this.#sessionsRoot, {
|
|
@@ -110,7 +214,19 @@ export class FileNativeWorldRevisionStore {
|
|
|
110
214
|
for (const entry of entries) {
|
|
111
215
|
if (!entry.isFile() || !sessionName.test(entry.name))
|
|
112
216
|
continue;
|
|
113
|
-
const
|
|
217
|
+
const sessionId = entry.name.slice(0, -5);
|
|
218
|
+
let session;
|
|
219
|
+
try {
|
|
220
|
+
session = await this.#readSession(sessionId);
|
|
221
|
+
if (hasDamagedGoogleSteps(session))
|
|
222
|
+
session = (await this.#damagedSession(sessionId)) ?? session;
|
|
223
|
+
}
|
|
224
|
+
catch (error) {
|
|
225
|
+
const damaged = await this.#damagedSession(sessionId);
|
|
226
|
+
if (damaged === null)
|
|
227
|
+
throw error;
|
|
228
|
+
session = damaged;
|
|
229
|
+
}
|
|
114
230
|
if (session.worldId === worldId)
|
|
115
231
|
sessions.push(session);
|
|
116
232
|
}
|
|
@@ -118,7 +234,10 @@ export class FileNativeWorldRevisionStore {
|
|
|
118
234
|
});
|
|
119
235
|
}
|
|
120
236
|
async findByCreationRequest(worldId, requestId) {
|
|
121
|
-
|
|
237
|
+
const match = (await this.listSessions(worldId)).find(({ creationRequestId }) => creationRequestId === requestId);
|
|
238
|
+
if (match?.damagedContinuation)
|
|
239
|
+
throw new Error("The historical conversation has damaged Google continuation; start a fresh model context with a new request ID");
|
|
240
|
+
return match ?? null;
|
|
122
241
|
}
|
|
123
242
|
deleteSession(worldId, sessionId) {
|
|
124
243
|
return this.#mutate(async () => {
|
|
@@ -126,6 +245,10 @@ export class FileNativeWorldRevisionStore {
|
|
|
126
245
|
if (session.worldId !== worldId)
|
|
127
246
|
throw new Error("World-revision conversation belongs to another world");
|
|
128
247
|
await rm(this.#sessionPath(sessionId));
|
|
248
|
+
await rm(join(this.#sessionsRoot, ".google-hops", sessionId), {
|
|
249
|
+
recursive: true,
|
|
250
|
+
force: true,
|
|
251
|
+
});
|
|
129
252
|
});
|
|
130
253
|
}
|
|
131
254
|
async #readEpoch(epochId) {
|
|
@@ -155,8 +278,34 @@ export class FileNativeWorldRevisionStore {
|
|
|
155
278
|
const session = validateSession(value);
|
|
156
279
|
if (session.sessionId !== sessionId)
|
|
157
280
|
throw new Error("World-revision conversation identity does not match its file");
|
|
281
|
+
for (const request of session.requests ?? [])
|
|
282
|
+
if (request.wireRequest !== undefined)
|
|
283
|
+
request.wireRequest = await readGoogleHops(join(this.#sessionsRoot, ".google-hops", sessionId), request.requestId, request.wireRequest);
|
|
158
284
|
return session;
|
|
159
285
|
}
|
|
286
|
+
async #damagedSession(sessionId) {
|
|
287
|
+
const raw = JSON.parse(await readFile(this.#sessionPath(sessionId), "utf8"));
|
|
288
|
+
const copy = withoutDamagedGoogleSteps(raw);
|
|
289
|
+
if (copy === null) {
|
|
290
|
+
if (hasDamagedGoogleSteps(raw))
|
|
291
|
+
throw new Error("Cannot safely identify the damaged historical conversation; settlement or identity is unverified");
|
|
292
|
+
return null;
|
|
293
|
+
}
|
|
294
|
+
const session = validateSession(copy);
|
|
295
|
+
if (session.sessionId !== sessionId ||
|
|
296
|
+
session.requests?.[0]?.requestId !== session.creationRequestId ||
|
|
297
|
+
!/^[A-Za-z0-9][A-Za-z0-9._:-]{0,159}$/u.test(session.creationRequestId))
|
|
298
|
+
throw new Error("Cannot safely identify the damaged historical conversation; its creation identity is unverified");
|
|
299
|
+
const epoch = await this.#readEpoch(session.epochId);
|
|
300
|
+
if (epoch.worldId !== session.worldId)
|
|
301
|
+
throw new Error("Cannot safely identify the damaged historical conversation; its world is inconsistent");
|
|
302
|
+
return {
|
|
303
|
+
...session,
|
|
304
|
+
damagedContinuation: true,
|
|
305
|
+
runStatus: "interrupted",
|
|
306
|
+
lastFailure: "Google continuation is damaged; start a fresh model context.",
|
|
307
|
+
};
|
|
308
|
+
}
|
|
160
309
|
async #afterMutations(read) {
|
|
161
310
|
await this.#mutationTail;
|
|
162
311
|
return read();
|
|
@@ -274,15 +423,51 @@ function validateSession(value) {
|
|
|
274
423
|
"lastFailure",
|
|
275
424
|
"authorization",
|
|
276
425
|
"pendingSettlement",
|
|
277
|
-
], [
|
|
278
|
-
|
|
426
|
+
], [
|
|
427
|
+
"requests",
|
|
428
|
+
"googleOutcomeUnknown",
|
|
429
|
+
...(value.schemaVersion === 3 ? ["retryDispatch", "editReceipts"] : []),
|
|
430
|
+
]) ||
|
|
431
|
+
(value.schemaVersion !== 1 &&
|
|
432
|
+
value.schemaVersion !== 2 &&
|
|
433
|
+
value.schemaVersion !== 3) ||
|
|
434
|
+
(value.editReceipts !== undefined &&
|
|
435
|
+
!validEditReceipts(value.editReceipts)) ||
|
|
436
|
+
(value.retryDispatch !== undefined &&
|
|
437
|
+
(!isRecord(value.retryDispatch) ||
|
|
438
|
+
!hasExactKeys(value.retryDispatch, [
|
|
439
|
+
"requestId",
|
|
440
|
+
"exchange",
|
|
441
|
+
"modelItemCount",
|
|
442
|
+
"state",
|
|
443
|
+
]) ||
|
|
444
|
+
!nonEmptyString(value.retryDispatch.requestId) ||
|
|
445
|
+
!count(value.retryDispatch.exchange) ||
|
|
446
|
+
!count(value.retryDispatch.modelItemCount) ||
|
|
447
|
+
!Array.isArray(value.requests) ||
|
|
448
|
+
!isRecord(value.requests.at(-1)) ||
|
|
449
|
+
value.requests.at(-1).requestId !==
|
|
450
|
+
value.retryDispatch.requestId ||
|
|
451
|
+
(value.runStatus !== "running" && value.runStatus !== "interrupted") ||
|
|
452
|
+
(value.retryDispatch.state === "retryable" &&
|
|
453
|
+
(!isRecord(value.modelBinding) ||
|
|
454
|
+
value.modelBinding.provider === "google_interactions")) ||
|
|
455
|
+
value.pendingSettlement !== null ||
|
|
456
|
+
!count(value.exchange) ||
|
|
457
|
+
(value.retryDispatch.exchange !== value.exchange &&
|
|
458
|
+
value.retryDispatch.exchange !== value.exchange + 1) ||
|
|
459
|
+
value.retryDispatch.modelItemCount !==
|
|
460
|
+
(Array.isArray(value.modelItems) ? value.modelItems.length : -1) ||
|
|
461
|
+
!["dispatching", "retryable", "blocked"].includes(String(value.retryDispatch.state)))) ||
|
|
279
462
|
(value.schemaVersion === 1
|
|
280
463
|
? value.requests !== undefined
|
|
281
|
-
:
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
464
|
+
: value.schemaVersion === 3 && value.requests === undefined
|
|
465
|
+
? value.retryDispatch !== undefined
|
|
466
|
+
: !validAuthoringRequests(value.requests, validPromptCompilation, {
|
|
467
|
+
modelItems: value.modelItems,
|
|
468
|
+
activeRequestId: value.activeRequestId,
|
|
469
|
+
completedRequestIds: value.completedRequestIds,
|
|
470
|
+
})) ||
|
|
286
471
|
typeof value.sessionId !== "string" ||
|
|
287
472
|
!nonEmptyString(value.worldId) ||
|
|
288
473
|
typeof value.worldTitle !== "string" ||
|
|
@@ -311,6 +496,10 @@ function validateSession(value) {
|
|
|
311
496
|
!Array.isArray(value.completedRequestIds) ||
|
|
312
497
|
!value.completedRequestIds.every((item) => typeof item === "string") ||
|
|
313
498
|
(value.lastFailure !== null && typeof value.lastFailure !== "string") ||
|
|
499
|
+
(value.googleOutcomeUnknown !== undefined &&
|
|
500
|
+
(typeof value.googleOutcomeUnknown !== "boolean" ||
|
|
501
|
+
!isRecord(value.modelBinding) ||
|
|
502
|
+
value.modelBinding.provider !== "google_interactions")) ||
|
|
314
503
|
!validAuthorization(value.authorization) ||
|
|
315
504
|
!validPendingSettlement(value.pendingSettlement) ||
|
|
316
505
|
!validPendingForSession(value.pendingSettlement, value.epochId, value.runStatus) ||
|
|
@@ -320,6 +509,31 @@ function validateSession(value) {
|
|
|
320
509
|
assertEpochId(value.epochId);
|
|
321
510
|
return structuredClone(value);
|
|
322
511
|
}
|
|
512
|
+
function validEditReceipts(value) {
|
|
513
|
+
if (!Array.isArray(value))
|
|
514
|
+
return false;
|
|
515
|
+
const ids = new Set();
|
|
516
|
+
return value.every((entry) => {
|
|
517
|
+
if (!isRecord(entry) ||
|
|
518
|
+
!hasExactKeys(entry, [
|
|
519
|
+
"requestId",
|
|
520
|
+
"messageId",
|
|
521
|
+
"message",
|
|
522
|
+
"filePolicy",
|
|
523
|
+
]) ||
|
|
524
|
+
typeof entry.requestId !== "string" ||
|
|
525
|
+
!/^[A-Za-z0-9][A-Za-z0-9._:-]{0,159}$/u.test(entry.requestId) ||
|
|
526
|
+
ids.has(entry.requestId) ||
|
|
527
|
+
!nonEmptyString(entry.messageId) ||
|
|
528
|
+
typeof entry.message !== "string" ||
|
|
529
|
+
entry.message.trim().length === 0 ||
|
|
530
|
+
entry.message.length > 64 * 1024 ||
|
|
531
|
+
(entry.filePolicy !== "keep" && entry.filePolicy !== "revert"))
|
|
532
|
+
return false;
|
|
533
|
+
ids.add(entry.requestId);
|
|
534
|
+
return true;
|
|
535
|
+
});
|
|
536
|
+
}
|
|
323
537
|
function validFiles(value) {
|
|
324
538
|
if (!Array.isArray(value))
|
|
325
539
|
return false;
|
|
@@ -452,6 +666,9 @@ function validModelToolCall(value) {
|
|
|
452
666
|
function validProviderState(value) {
|
|
453
667
|
if (!isRecord(value))
|
|
454
668
|
return false;
|
|
669
|
+
if (value.protocol === "google_interactions")
|
|
670
|
+
return (hasExactKeys(value, ["protocol", "steps"]) &&
|
|
671
|
+
validGoogleInteractionsSteps(value.steps));
|
|
455
672
|
if (value.protocol === "chat_completions")
|
|
456
673
|
return hasExactKeys(value, ["protocol", "assistantMessage"]);
|
|
457
674
|
if (value.protocol === "openai_responses")
|
|
@@ -509,7 +726,8 @@ function validModelBinding(value) {
|
|
|
509
726
|
], ["cacheStrategy"]) &&
|
|
510
727
|
(value.provider === "chat_completions" ||
|
|
511
728
|
value.provider === "openai_responses" ||
|
|
512
|
-
value.provider === "anthropic_messages"
|
|
729
|
+
value.provider === "anthropic_messages" ||
|
|
730
|
+
value.provider === "google_interactions") &&
|
|
513
731
|
typeof value.endpointFingerprint === "string" &&
|
|
514
732
|
typeof value.modelId === "string" &&
|
|
515
733
|
count(value.contextWindowTokens) &&
|
|
@@ -531,7 +749,10 @@ function validModelUsage(value) {
|
|
|
531
749
|
"totalTokens",
|
|
532
750
|
];
|
|
533
751
|
if (!isRecord(value) ||
|
|
534
|
-
!hasExactKeys(value, [...fields, "provenance"]) ||
|
|
752
|
+
!hasExactKeys(value, [...fields, "provenance"], ["providerRaw", "accounting"]) ||
|
|
753
|
+
(value.providerRaw !== undefined && !isRecord(value.providerRaw)) ||
|
|
754
|
+
(value.accounting !== undefined &&
|
|
755
|
+
value.accounting !== "google_interactions") ||
|
|
535
756
|
!fields.every((field) => value[field] === null || count(value[field])) ||
|
|
536
757
|
!isRecord(value.provenance) ||
|
|
537
758
|
!hasExactKeys(value.provenance, fields))
|
|
@@ -594,7 +815,7 @@ function validPendingSettlement(value) {
|
|
|
594
815
|
function validPendingForSession(pending, epochId, runStatus) {
|
|
595
816
|
return (pending === null ||
|
|
596
817
|
(isRecord(pending) &&
|
|
597
|
-
runStatus === "running" &&
|
|
818
|
+
(runStatus === "running" || runStatus === "interrupted") &&
|
|
598
819
|
pending.epochId === epochId));
|
|
599
820
|
}
|
|
600
821
|
function validToolResult(value) {
|