@oar-sh/oar 0.9.15 → 0.9.17
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/.github/extensions/web-relay/polling/polling-loop.mjs +14 -87
- package/CHANGELOG.md +305 -0
- package/README.md +12 -11
- package/package.json +2 -1
- package/server/claude-worker/claude-attachments.mjs +7 -4
- package/server/claude-worker/claude-remote-relay-tool.mjs +36 -1
- package/server/claude-worker/claude-sdk-adapter.mjs +167 -9
- package/server/claude-worker/claude-session-process.mjs +131 -33
- package/server/claude-worker/claude-session-worker-main.mjs +266 -0
- package/server/claude-worker/claude-session-worker.mjs +2 -253
- package/server/claude-worker/claude-turn-failure.mjs +8 -0
- package/server/claude-worker/claude-turn-publisher.mjs +282 -13
- package/server/claude-worker/claude-usage-totals.mjs +108 -0
- package/server/claude-worker/sdk-message-normalizer.mjs +55 -0
- package/server/copilot-worker/copilot-sdk-adapter.mjs +18 -4
- package/server/copilot-worker/copilot-sdk-session-process.mjs +73 -7
- package/server/db-schema.mjs +115 -0
- package/server/deepseek-worker/deepseek-claude-backend.mjs +433 -0
- package/server/deepseek-worker/deepseek-session-worker.mjs +37 -0
- package/server/migrations/0019-relay-event-subscription-options.mjs +106 -0
- package/server/migrations/0020-conversation-may-create-sessions.mjs +67 -0
- package/server/migrations/0021-conversation-group-agent-marks.mjs +77 -0
- package/server/migrations/0022-relay-schedules.mjs +142 -0
- package/server/migrations/0023-relay-asks.mjs +141 -0
- package/server/migrations/0024-deepseek-usage-totals.mjs +151 -0
- package/server/migrations/0025-deepseek-usage-requests-daily.mjs +179 -0
- package/server/migrations/0026-deepseek-usage-served-models.mjs +222 -0
- package/server/migrations/0027-deepseek-usage-checkpoint-runs.mjs +101 -0
- package/server/migrations/0028-deepseek-usage-checkpoint-request-runs.mjs +99 -0
- package/server/migrations/0029-deepseek-balance-rises.mjs +99 -0
- package/server/migrations/0030-deepseek-usage-actuals.mjs +123 -0
- package/server/public/app/api-client.js +53 -0
- package/server/public/app/ask-user-view.js +3 -0
- package/server/public/app/bootstrap.js +162 -16
- package/server/public/app/context-tier-options.mjs +4 -0
- package/server/public/app/context-usage-view.mjs +17 -0
- package/server/public/app/conversation-group-order.mjs +35 -0
- package/server/public/app/conversation-provider-indicator.mjs +7 -0
- package/server/public/app/conversation-view.js +2 -0
- package/server/public/app/deepseek-settings-ui.js +342 -0
- package/server/public/app/inbox-ui.js +367 -0
- package/server/public/app/inbox-view.mjs +370 -0
- package/server/public/app/journal-view.js +54 -5
- package/server/public/app/model-selector-options.mjs +11 -0
- package/server/public/app/model-vision-support.mjs +2 -0
- package/server/public/app/no-conversation-state.mjs +1 -1
- package/server/public/app/plan-usage-view.mjs +165 -13
- package/server/public/app/provider-readiness.mjs +4 -1
- package/server/public/app/relay-error-ctas.mjs +8 -0
- package/server/public/app/relay-event-subscriptions-ui.js +4 -2
- package/server/public/app/relay-event-view.mjs +33 -7
- package/server/public/app/relay-schedule-view.mjs +119 -0
- package/server/public/app/relay-schedules-ui.js +172 -0
- package/server/public/app/settings-modal.js +11 -0
- package/server/public/app/settings-tabs.js +1 -1
- package/server/public/app/socket-handlers.js +37 -3
- package/server/public/app/store.js +18 -5
- package/server/public/index.html +567 -35
- package/server/relay-tools.md +18 -3
- package/server/repositories/conversation-group-repository.mjs +110 -17
- package/server/repositories/remote-relay-repository.mjs +20 -2
- package/server/repositories/session-repository.mjs +7 -1
- package/server/routes/ask-user-routes.mjs +57 -3
- package/server/routes/cache-routes.mjs +6 -0
- package/server/routes/conversation-group-routes.mjs +19 -3
- package/server/routes/deepseek-usage-import-routes.mjs +72 -0
- package/server/routes/messages-routes.mjs +195 -18
- package/server/routes/relay-ask-routes.mjs +387 -0
- package/server/routes/relay-event-routes.mjs +3 -1
- package/server/routes/relay-schedule-routes.mjs +57 -0
- package/server/routes/sessions-routes.mjs +932 -97
- package/server/server-runtime.mjs +203 -11
- package/server/services/about-service.mjs +1 -0
- package/server/services/cache-rebuild-service.mjs +19 -2
- package/server/services/claude-session-leftovers.mjs +226 -0
- package/server/services/conversation-preferences-service.mjs +17 -0
- package/server/services/deepseek-balance-service.mjs +102 -0
- package/server/services/deepseek-settings-service.mjs +380 -0
- package/server/services/deepseek-usage-import.mjs +471 -0
- package/server/services/model-variant-catalog-service.mjs +1 -0
- package/server/services/plan-usage-contract.mjs +100 -5
- package/server/services/plan-usage-deepseek.mjs +931 -0
- package/server/services/plan-usage-service.mjs +431 -0
- package/server/services/provider-model-selection.mjs +1 -0
- package/server/services/provider-reasoning-effort.mjs +15 -2
- package/server/services/relay-ask-link-service.mjs +174 -0
- package/server/services/relay-ask-service.mjs +604 -0
- package/server/services/relay-event-service.mjs +589 -73
- package/server/services/relay-schedule-service.mjs +596 -0
- package/server/services/remote-relay-caller-context.mjs +89 -20
- package/server/services/remote-relay-dispatcher.mjs +958 -31
- package/server/services/session-worker-launch-service.mjs +233 -82
- package/server/services/worker-secret-redaction.mjs +318 -0
- package/shared/context-window-fallbacks.mjs +3 -0
- package/shared/deepseek-api.mjs +137 -0
- package/shared/deepseek-models.mjs +114 -0
- package/shared/deepseek-pricing.mjs +146 -0
- package/shared/host-claude-session-env.mjs +101 -0
- package/shared/model-id.mjs +7 -0
- package/shared/preview-tool-core.mjs +1 -1
- package/shared/provider-routing.mjs +2 -2
- package/shared/relay-asks.mjs +145 -0
- package/shared/relay-events.mjs +268 -18
- package/shared/relay-schedules.mjs +128 -0
- package/shared/remote-relay-contract.mjs +554 -26
- package/shared/remote-relay-tool-core.mjs +16 -5
- package/shared/steer-settle-failure.mjs +1 -0
- package/shared/worker-runtime/direct-openai-image.mjs +128 -0
- package/shared/worker-runtime/worker-log-file.mjs +60 -0
|
@@ -112,8 +112,13 @@ import { STEER_FOLDED_TEXT, STEER_STOPPED_TEXT, STEER_TURN_FAILED_TEXT } from '.
|
|
|
112
112
|
import { buildSteerSettleFailure } from '../../shared/steer-settle-failure.mjs';
|
|
113
113
|
import { shouldEmitStreamUpdate } from '../../shared/stream-emit-gating.mjs';
|
|
114
114
|
import { withSteerNote } from '../../shared/steer-note.mjs';
|
|
115
|
-
import {
|
|
115
|
+
import { isRelayAutomatedDelivery } from '../../shared/relay-events.mjs';
|
|
116
116
|
import { isTransientRelayError } from '../../shared/worker-runtime/relay-errors.mjs';
|
|
117
|
+
import {
|
|
118
|
+
isOpenAIImageTerminalError,
|
|
119
|
+
runDirectOpenAIImageTurn,
|
|
120
|
+
shouldUseDirectOpenAIImageApi,
|
|
121
|
+
} from '../../shared/worker-runtime/direct-openai-image.mjs';
|
|
117
122
|
import {
|
|
118
123
|
createTurnLiveness,
|
|
119
124
|
createTurnStalledError,
|
|
@@ -556,6 +561,12 @@ export function createCopilotSdkSessionRunner({
|
|
|
556
561
|
// terminal error until the publish lands, so recovery can never re-run them
|
|
557
562
|
// (see publishSettleMarker).
|
|
558
563
|
const settlingMessages = new Map();
|
|
564
|
+
// Image-model rows running on the relay's image routes (id → message). They
|
|
565
|
+
// never reach the runtime, so no turn owns them; the heartbeat and the crash
|
|
566
|
+
// guard still have to.
|
|
567
|
+
const directImageMessages = new Map();
|
|
568
|
+
// `openai` on a BYOK worker; the failure notes name the provider.
|
|
569
|
+
const workerProvider = String(env.COPILOT_PROVIDER_TYPE || '').trim().toLowerCase();
|
|
559
570
|
// Settle markers that could not be posted even terminally; the heartbeat
|
|
560
571
|
// hands them to the relay to fail (id → terminalError).
|
|
561
572
|
const settleFailedTerminals = new Map();
|
|
@@ -3728,7 +3739,7 @@ export function createCopilotSdkSessionRunner({
|
|
|
3728
3739
|
// afterwards: a runtime that died or went silent under a Stop used to put
|
|
3729
3740
|
// the watchdog's failure on every row instead.
|
|
3730
3741
|
if (failure && !turn.aborted) {
|
|
3731
|
-
const classified = classifyCopilotTurnException(failure);
|
|
3742
|
+
const classified = classifyCopilotTurnException(failure, { provider: workerProvider });
|
|
3732
3743
|
dbg('copilot turn failed', turn.message?.id || '(continuation)', classified.detail);
|
|
3733
3744
|
const running = turn.currentOwner || turn.primaryEntry;
|
|
3734
3745
|
for (const entry of pending) {
|
|
@@ -3747,7 +3758,7 @@ export function createCopilotSdkSessionRunner({
|
|
|
3747
3758
|
return;
|
|
3748
3759
|
}
|
|
3749
3760
|
if (result?.isError) {
|
|
3750
|
-
const classified = classifyCopilotSessionError(result.errorData || { message: result.errorMessage });
|
|
3761
|
+
const classified = classifyCopilotSessionError(result.errorData || { message: result.errorMessage }, { provider: workerProvider });
|
|
3751
3762
|
dbg('turn failed', turn.message?.id || '(continuation)', classified.stableCode);
|
|
3752
3763
|
const running = turn.currentOwner || turn.primaryEntry;
|
|
3753
3764
|
for (const entry of pending) {
|
|
@@ -4117,6 +4128,7 @@ export function createCopilotSdkSessionRunner({
|
|
|
4117
4128
|
dbg('continuation output dropped (no relay row)');
|
|
4118
4129
|
const classified = classifyCopilotTurnException(
|
|
4119
4130
|
turn.failure || new Error('the relay refused a continuation row for this turn'),
|
|
4131
|
+
{ provider: workerProvider },
|
|
4120
4132
|
);
|
|
4121
4133
|
for (const entry of turn.entries) {
|
|
4122
4134
|
if (entry.settled || entry.turn !== turn) continue;
|
|
@@ -4456,7 +4468,7 @@ export function createCopilotSdkSessionRunner({
|
|
|
4456
4468
|
// Not in a continuation: there the running work is the runtime's own
|
|
4457
4469
|
// follow-up, not a request of the user's to keep going with.
|
|
4458
4470
|
// Nor in an event message the relay wrote: the note speaks as the user.
|
|
4459
|
-
const prompt = withRelayContext(context?.prefix, turn.kind === 'continuation' ||
|
|
4471
|
+
const prompt = withRelayContext(context?.prefix, turn.kind === 'continuation' || isRelayAutomatedDelivery(message) ? body : withSteerNote(body));
|
|
4460
4472
|
// Re-checked AFTER the awaits and before anything is sent or registered.
|
|
4461
4473
|
// Nothing has been sent yet, so handing the row back to the normal path is
|
|
4462
4474
|
// free.
|
|
@@ -4821,6 +4833,9 @@ export function createCopilotSdkSessionRunner({
|
|
|
4821
4833
|
async function handlePendingPayload(pending) {
|
|
4822
4834
|
const message = pending?.message || null;
|
|
4823
4835
|
if (!message) return false;
|
|
4836
|
+
// An image model is no chat model: its row goes to the relay's image
|
|
4837
|
+
// routes, whatever the runtime is doing, and never into the runtime.
|
|
4838
|
+
if (shouldUseDirectOpenAIImageApi(message)) return runDirectImageTurn(message);
|
|
4824
4839
|
// Held (a card is open, a compaction is running, a tool of the main agent
|
|
4825
4840
|
// is running, the turn-opening prompt is not sent yet): hand the row back
|
|
4826
4841
|
// with no retry penalty; the relay re-delivers it when the hold ends. An
|
|
@@ -4850,7 +4865,7 @@ export function createCopilotSdkSessionRunner({
|
|
|
4850
4865
|
if (outcome !== NOT_STEERED) return outcome;
|
|
4851
4866
|
} catch (error) {
|
|
4852
4867
|
dbg('steering failed', message.id, error?.message || String(error));
|
|
4853
|
-
const classified = classifyCopilotTurnException(error);
|
|
4868
|
+
const classified = classifyCopilotTurnException(error, { provider: workerProvider });
|
|
4854
4869
|
await publishResponse(message, {
|
|
4855
4870
|
text: classified.text,
|
|
4856
4871
|
model: null,
|
|
@@ -4863,6 +4878,54 @@ export function createCopilotSdkSessionRunner({
|
|
|
4863
4878
|
return runTurn(turn);
|
|
4864
4879
|
}
|
|
4865
4880
|
|
|
4881
|
+
/**
|
|
4882
|
+
* One image-model row (shared/worker-runtime/direct-openai-image.mjs). With
|
|
4883
|
+
* an image operation the relay's execute route publishes the reply, the
|
|
4884
|
+
* failure or the requeue itself; without one the shared helper publishes
|
|
4885
|
+
* the reply, and a refusal by the provider is published here as the row's
|
|
4886
|
+
* failure. Anything else requeues the row, as on the extension engine.
|
|
4887
|
+
*/
|
|
4888
|
+
async function runDirectImageTurn(message) {
|
|
4889
|
+
const id = String(message.id || '');
|
|
4890
|
+
directImageMessages.set(id, message);
|
|
4891
|
+
touch();
|
|
4892
|
+
try {
|
|
4893
|
+
const result = await runDirectOpenAIImageTurn({
|
|
4894
|
+
api,
|
|
4895
|
+
message,
|
|
4896
|
+
// An edit can take minutes, longer than fetch waits for headers.
|
|
4897
|
+
requestOptions: { longCall: true },
|
|
4898
|
+
responseFields: attemptFields(message),
|
|
4899
|
+
});
|
|
4900
|
+
dbg('image turn', message.id, result.via, result.outcome);
|
|
4901
|
+
} catch (error) {
|
|
4902
|
+
if (isOpenAIImageTerminalError(error)) {
|
|
4903
|
+
dbg('image turn refused by OpenAI', message.id, error.message);
|
|
4904
|
+
await publishResponse(message, {
|
|
4905
|
+
text: error.message,
|
|
4906
|
+
model: null,
|
|
4907
|
+
terminalError: {
|
|
4908
|
+
kind: 'openai-image-failed',
|
|
4909
|
+
// The code the relay's image operation uses for the same refusal.
|
|
4910
|
+
code: 'image-provider-rejected',
|
|
4911
|
+
stableCode: 'image-provider-rejected',
|
|
4912
|
+
message: error.message,
|
|
4913
|
+
...(error.detail ? { detail: String(error.detail) } : {}),
|
|
4914
|
+
failedAt: new Date().toISOString(),
|
|
4915
|
+
queueMessageId: id || null,
|
|
4916
|
+
},
|
|
4917
|
+
});
|
|
4918
|
+
} else {
|
|
4919
|
+
dbg('image turn failed; requeueing', message.id, error?.message || String(error));
|
|
4920
|
+
await api('POST', '/api/requeue', { messageId: message.id, ...attemptFields(message) }).catch(() => {});
|
|
4921
|
+
}
|
|
4922
|
+
} finally {
|
|
4923
|
+
directImageMessages.delete(id);
|
|
4924
|
+
touch();
|
|
4925
|
+
}
|
|
4926
|
+
return true;
|
|
4927
|
+
}
|
|
4928
|
+
|
|
4866
4929
|
// --------------------------------------------------------------- teardown --
|
|
4867
4930
|
|
|
4868
4931
|
function getActiveQueueMessageId() {
|
|
@@ -4872,6 +4935,7 @@ export function createCopilotSdkSessionRunner({
|
|
|
4872
4935
|
const id = String(entry.message?.id || '');
|
|
4873
4936
|
if (id && !entry.released) return id;
|
|
4874
4937
|
}
|
|
4938
|
+
for (const id of directImageMessages.keys()) return id;
|
|
4875
4939
|
return '';
|
|
4876
4940
|
}
|
|
4877
4941
|
|
|
@@ -4911,6 +4975,7 @@ export function createCopilotSdkSessionRunner({
|
|
|
4911
4975
|
for (const { message, variant } of settlingMessages.values()) {
|
|
4912
4976
|
push(message, buildSteerSettleFailure(message, { variant, agentLabel: SETTLE_AGENT_LABEL }));
|
|
4913
4977
|
}
|
|
4978
|
+
for (const message of directImageMessages.values()) push(message);
|
|
4914
4979
|
return entries;
|
|
4915
4980
|
}
|
|
4916
4981
|
|
|
@@ -4949,8 +5014,9 @@ export function createCopilotSdkSessionRunner({
|
|
|
4949
5014
|
// registry and refuses ids it does not know.
|
|
4950
5015
|
stopBackgroundTask,
|
|
4951
5016
|
// "Active" spans both ownerships: a settled turn still publishing must
|
|
4952
|
-
// keep the worker's idle/shutdown gates closed just like a running one
|
|
4953
|
-
|
|
5017
|
+
// keep the worker's idle/shutdown gates closed just like a running one,
|
|
5018
|
+
// and so must an image row on the relay's image routes.
|
|
5019
|
+
isTurnActive: () => !!activeTurn || publishingTurns.size > 0 || directImageMessages.size > 0,
|
|
4954
5020
|
dispose,
|
|
4955
5021
|
// The turn's tokens/cost/TTFT, as posted to `/api/copilot-plan-usage`.
|
|
4956
5022
|
getLastTurnUsage: () => lastTurnUsage,
|
package/server/db-schema.mjs
CHANGED
|
@@ -24,6 +24,18 @@ import { migrateConversationGroupPosition } from './migrations/0015-conversation
|
|
|
24
24
|
import { migrateShareAccessLog } from './migrations/0016-share-access-log.mjs';
|
|
25
25
|
import { migrateConversationHistoryIndexes } from './migrations/0017-conversation-history-indexes.mjs';
|
|
26
26
|
import { migrateBackgroundTaskRows } from './migrations/0018-background-task-rows.mjs';
|
|
27
|
+
import { migrateRelayEventSubscriptionOptions } from './migrations/0019-relay-event-subscription-options.mjs';
|
|
28
|
+
import { migrateConversationMayCreateSessions } from './migrations/0020-conversation-may-create-sessions.mjs';
|
|
29
|
+
import { migrateConversationGroupAgentMarks } from './migrations/0021-conversation-group-agent-marks.mjs';
|
|
30
|
+
import { migrateRelaySchedules } from './migrations/0022-relay-schedules.mjs';
|
|
31
|
+
import { migrateRelayAsks } from './migrations/0023-relay-asks.mjs';
|
|
32
|
+
import { migrateDeepSeekUsageTotals } from './migrations/0024-deepseek-usage-totals.mjs';
|
|
33
|
+
import { migrateDeepSeekUsageRequestsDaily } from './migrations/0025-deepseek-usage-requests-daily.mjs';
|
|
34
|
+
import { migrateDeepSeekUsageServedModels } from './migrations/0026-deepseek-usage-served-models.mjs';
|
|
35
|
+
import { migrateDeepSeekUsageCheckpointRuns } from './migrations/0027-deepseek-usage-checkpoint-runs.mjs';
|
|
36
|
+
import { migrateDeepSeekUsageCheckpointRequestRuns } from './migrations/0028-deepseek-usage-checkpoint-request-runs.mjs';
|
|
37
|
+
import { migrateDeepSeekBalanceRises } from './migrations/0029-deepseek-balance-rises.mjs';
|
|
38
|
+
import { migrateDeepSeekUsageActuals } from './migrations/0030-deepseek-usage-actuals.mjs';
|
|
27
39
|
import { migrateImageConversationSchema } from './repositories/image-conversation-repository.mjs';
|
|
28
40
|
|
|
29
41
|
// Mirrors DEFAULT_RELAY_MODE in server-runtime.mjs; used only by the one-time
|
|
@@ -855,6 +867,109 @@ try {
|
|
|
855
867
|
console.warn(`[background-tasks] migration 0018 failed; retrying on next boot: ${error?.message || error}`);
|
|
856
868
|
}
|
|
857
869
|
|
|
870
|
+
// Options of relay event subscriptions (digest, quiet hours, exclude) and the
|
|
871
|
+
// watcher's own prompts: columns on 0011's table and one table. The event
|
|
872
|
+
// service checks for them and refuses the options without them, so a failure
|
|
873
|
+
// is logged and retried next boot like 0018.
|
|
874
|
+
try {
|
|
875
|
+
migrateRelayEventSubscriptionOptions(db);
|
|
876
|
+
} catch (error) {
|
|
877
|
+
console.warn(`[relay-events] migration 0019 failed; retrying on next boot: ${error?.message || error}`);
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
// The owner's "agents in this conversation may start sessions": one column.
|
|
881
|
+
// Without it nobody can turn the switch on (the preferences route refuses
|
|
882
|
+
// it) and the one-level rule holds for every session, so a failure is logged
|
|
883
|
+
// and retried next boot like 0019.
|
|
884
|
+
try {
|
|
885
|
+
migrateConversationMayCreateSessions(db);
|
|
886
|
+
} catch (error) {
|
|
887
|
+
console.warn(`[remote-relays] migration 0020 failed; retrying on next boot: ${error?.message || error}`);
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
// What an agent's update_session may do to a group: two columns. Without
|
|
891
|
+
// them an owner's group an agent emptied is kept until the next boot repair
|
|
892
|
+
// only, so a failure is logged and retried next boot like 0020.
|
|
893
|
+
try {
|
|
894
|
+
migrateConversationGroupAgentMarks(db);
|
|
895
|
+
} catch (error) {
|
|
896
|
+
console.warn(`[session-groups] migration 0021 failed; retrying on next boot: ${error?.message || error}`);
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
// Relay schedules: one new table. The schedule service checks for it and
|
|
900
|
+
// refuses the schedule actions without it, so a failure is logged and
|
|
901
|
+
// retried next boot like 0021.
|
|
902
|
+
try {
|
|
903
|
+
migrateRelaySchedules(db);
|
|
904
|
+
} catch (error) {
|
|
905
|
+
console.warn(`[relay-schedules] migration 0022 failed; retrying on next boot: ${error?.message || error}`);
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
// Questions that don't block (remote_relay ask): one new table. The ask
|
|
909
|
+
// service checks for it and refuses the ask actions without it, so a failure
|
|
910
|
+
// is logged and retried next boot like 0022.
|
|
911
|
+
try {
|
|
912
|
+
migrateRelayAsks(db);
|
|
913
|
+
} catch (error) {
|
|
914
|
+
console.warn(`[relay-asks] migration 0023 failed; retrying on next boot: ${error?.message || error}`);
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
// DeepSeek usage totals: one new table. The plan usage service creates it
|
|
918
|
+
// itself as well, so a failure here is logged and retried next boot like 0023.
|
|
919
|
+
try {
|
|
920
|
+
migrateDeepSeekUsageTotals(db);
|
|
921
|
+
} catch (error) {
|
|
922
|
+
console.warn(`[deepseek-usage] migration 0024 failed; retrying on next boot: ${error?.message || error}`);
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
// DeepSeek search/fetch counts, daily spend and balance reference: four
|
|
926
|
+
// columns on 0024's table and two tables, handled like 0024.
|
|
927
|
+
try {
|
|
928
|
+
migrateDeepSeekUsageRequestsDaily(db);
|
|
929
|
+
} catch (error) {
|
|
930
|
+
console.warn(`[deepseek-usage] migration 0025 failed; retrying on next boot: ${error?.message || error}`);
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
// DeepSeek usage booked under a Claude model name is folded into the DeepSeek
|
|
934
|
+
// model that served it, handled like 0024.
|
|
935
|
+
try {
|
|
936
|
+
migrateDeepSeekUsageServedModels(db);
|
|
937
|
+
} catch (error) {
|
|
938
|
+
console.warn(`[deepseek-usage] migration 0026 failed; retrying on next boot: ${error?.message || error}`);
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
// The DeepSeek usage checkpoint learns the worker process's run id and its
|
|
942
|
+
// search and fetch counts: three columns on 0024's table, handled like 0024.
|
|
943
|
+
try {
|
|
944
|
+
migrateDeepSeekUsageCheckpointRuns(db);
|
|
945
|
+
} catch (error) {
|
|
946
|
+
console.warn(`[deepseek-usage] migration 0027 failed; retrying on next boot: ${error?.message || error}`);
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
// The checkpoint's search and fetch counts get a run id of their own: one
|
|
950
|
+
// column on 0024's table, handled like 0024.
|
|
951
|
+
try {
|
|
952
|
+
migrateDeepSeekUsageCheckpointRequestRuns(db);
|
|
953
|
+
} catch (error) {
|
|
954
|
+
console.warn(`[deepseek-usage] migration 0028 failed; retrying on next boot: ${error?.message || error}`);
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
// The balance reference notes when the balance last rose: one column on
|
|
958
|
+
// 0025's table, handled like 0025.
|
|
959
|
+
try {
|
|
960
|
+
migrateDeepSeekBalanceRises(db);
|
|
961
|
+
} catch (error) {
|
|
962
|
+
console.warn(`[deepseek-usage] migration 0029 failed; retrying on next boot: ${error?.message || error}`);
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
// The imported figures of DeepSeek's usage export: a table of its own, handled
|
|
966
|
+
// like 0024.
|
|
967
|
+
try {
|
|
968
|
+
migrateDeepSeekUsageActuals(db);
|
|
969
|
+
} catch (error) {
|
|
970
|
+
console.warn(`[deepseek-usage] migration 0030 failed; retrying on next boot: ${error?.message || error}`);
|
|
971
|
+
}
|
|
972
|
+
|
|
858
973
|
const runtimeSessionColumns = db.prepare(`PRAGMA table_info(runtime_sessions)`).all().map((c) => c.name);
|
|
859
974
|
if (runtimeSessionColumns.length) {
|
|
860
975
|
if (!runtimeSessionColumns.includes('strategy')) {
|