@retaw106/mmc-oc 1.2.3 → 2.1.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.js +7095 -0
- package/dist/config/index.d.ts +0 -12
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/legacy-harness-blocks.d.ts +27 -0
- package/dist/config/legacy-harness-blocks.d.ts.map +1 -0
- package/dist/config/live-run-config.d.ts.map +1 -1
- package/dist/config/live-snapshot.d.ts +2 -1
- package/dist/config/live-snapshot.d.ts.map +1 -1
- package/dist/config/project-security.d.ts +4 -5
- package/dist/config/project-security.d.ts.map +1 -1
- package/dist/config/raw-loader.d.ts +7 -26
- package/dist/config/raw-loader.d.ts.map +1 -1
- package/dist/config/schema/magic-context.d.ts +164 -259
- package/dist/config/schema/magic-context.d.ts.map +1 -1
- package/dist/config/variable.d.ts +8 -0
- package/dist/config/variable.d.ts.map +1 -1
- package/dist/config-init.js +5595 -0
- package/dist/{context-a6px04s0.js → context-vhcstgs3.js} +5758 -4727
- package/dist/{derive-budgets-fhk00zv8.js → derive-budgets-rjjz5f7y.js} +2 -2
- package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
- package/dist/features/magic-context/memory/types.d.ts +1 -0
- package/dist/features/magic-context/memory/types.d.ts.map +1 -1
- package/dist/features/magic-context/message-index.d.ts +2 -0
- package/dist/features/magic-context/message-index.d.ts.map +1 -1
- package/dist/features/magic-context/migration-v3-perf-schema.d.ts +8 -0
- package/dist/features/magic-context/migration-v3-perf-schema.d.ts.map +1 -0
- package/dist/features/magic-context/migration-v4-temporal-decisions.d.ts +12 -0
- package/dist/features/magic-context/migration-v4-temporal-decisions.d.ts.map +1 -0
- package/dist/features/magic-context/migrations.d.ts.map +1 -1
- package/dist/features/magic-context/overflow-detection.d.ts +6 -0
- package/dist/features/magic-context/overflow-detection.d.ts.map +1 -1
- package/dist/features/magic-context/reclaim-protection.d.ts +15 -10
- package/dist/features/magic-context/reclaim-protection.d.ts.map +1 -1
- package/dist/features/magic-context/session-cache-ttl.d.ts +4 -2
- package/dist/features/magic-context/session-cache-ttl.d.ts.map +1 -1
- package/dist/features/magic-context/session-project-storage.d.ts +8 -2
- package/dist/features/magic-context/session-project-storage.d.ts.map +1 -1
- package/dist/features/magic-context/storage-db.d.ts +1 -1
- package/dist/features/magic-context/storage-db.d.ts.map +1 -1
- package/dist/features/magic-context/storage-historian-runs.d.ts +2 -0
- package/dist/features/magic-context/storage-historian-runs.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-persisted.d.ts +12 -0
- package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-session.d.ts +6 -0
- package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
- package/dist/features/magic-context/storage-ops.d.ts +2 -0
- package/dist/features/magic-context/storage-ops.d.ts.map +1 -1
- package/dist/features/magic-context/storage-session-tables.d.ts.map +1 -1
- package/dist/features/magic-context/storage-tags.d.ts +17 -4
- package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
- package/dist/features/magic-context/storage.d.ts +2 -2
- package/dist/features/magic-context/storage.d.ts.map +1 -1
- package/dist/features/magic-context/temporal-decisions.d.ts +10 -0
- package/dist/features/magic-context/temporal-decisions.d.ts.map +1 -0
- package/dist/features/magic-context/tool-definition-tokens.d.ts +3 -0
- package/dist/features/magic-context/tool-definition-tokens.d.ts.map +1 -1
- package/dist/features/magic-context/transform-decision-log.d.ts +3 -1
- package/dist/features/magic-context/transform-decision-log.d.ts.map +1 -1
- package/dist/hooks/magic-context/active-anthropic-turn.d.ts +8 -0
- package/dist/hooks/magic-context/active-anthropic-turn.d.ts.map +1 -0
- package/dist/hooks/magic-context/apply-operations.d.ts +15 -0
- package/dist/hooks/magic-context/apply-operations.d.ts.map +1 -1
- package/dist/hooks/magic-context/auto-search-deadline.d.ts +10 -3
- package/dist/hooks/magic-context/auto-search-deadline.d.ts.map +1 -1
- package/dist/hooks/magic-context/auto-search-runner.d.ts +1 -1
- package/dist/hooks/magic-context/auto-search-runner.d.ts.map +1 -1
- package/dist/hooks/magic-context/caveman-cleanup.d.ts.map +1 -1
- package/dist/hooks/magic-context/channel2-cycle.d.ts +2 -0
- package/dist/hooks/magic-context/channel2-cycle.d.ts.map +1 -1
- package/dist/hooks/magic-context/compaction-marker-manager.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-render-epoch.d.ts +8 -0
- package/dist/hooks/magic-context/compartment-render-epoch.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-partial-recomp.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-recomp.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-types.d.ts +3 -5
- package/dist/hooks/magic-context/compartment-runner-types.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner.d.ts +2 -1
- package/dist/hooks/magic-context/compartment-runner.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-trigger.d.ts +3 -1
- package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -1
- package/dist/hooks/magic-context/ctx-reduce-availability.d.ts +12 -0
- package/dist/hooks/magic-context/ctx-reduce-availability.d.ts.map +1 -1
- package/dist/hooks/magic-context/decision-calibration.d.ts +3 -0
- package/dist/hooks/magic-context/decision-calibration.d.ts.map +1 -1
- package/dist/hooks/magic-context/emergency-drop.d.ts +2 -0
- package/dist/hooks/magic-context/emergency-drop.d.ts.map +1 -1
- package/dist/hooks/magic-context/emergency-fail-closed.d.ts +21 -1
- package/dist/hooks/magic-context/emergency-fail-closed.d.ts.map +1 -1
- package/dist/hooks/magic-context/final-wire-token-estimate.d.ts +32 -1
- package/dist/hooks/magic-context/final-wire-token-estimate.d.ts.map +1 -1
- package/dist/hooks/magic-context/heuristic-cleanup.d.ts +2 -0
- package/dist/hooks/magic-context/heuristic-cleanup.d.ts.map +1 -1
- package/dist/hooks/magic-context/historian-drain-gate.d.ts +11 -0
- package/dist/hooks/magic-context/historian-drain-gate.d.ts.map +1 -0
- package/dist/hooks/magic-context/inject-compartments.d.ts +10 -8
- package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
- package/dist/hooks/magic-context/latest-assistant-turn.d.ts +25 -0
- package/dist/hooks/magic-context/latest-assistant-turn.d.ts.map +1 -0
- package/dist/hooks/magic-context/lkg-measured-request.d.ts +69 -0
- package/dist/hooks/magic-context/lkg-measured-request.d.ts.map +1 -0
- package/dist/hooks/magic-context/lkg-replay-fit.d.ts +118 -0
- package/dist/hooks/magic-context/lkg-replay-fit.d.ts.map +1 -0
- package/dist/hooks/magic-context/lkg-replay.d.ts +2 -0
- package/dist/hooks/magic-context/lkg-replay.d.ts.map +1 -1
- package/dist/hooks/magic-context/protected-tail-boundary.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-formatting.d.ts +3 -0
- package/dist/hooks/magic-context/read-session-formatting.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-true-raw-tokens.d.ts.map +1 -1
- package/dist/hooks/magic-context/reasoning-budget-status.d.ts +15 -0
- package/dist/hooks/magic-context/reasoning-budget-status.d.ts.map +1 -0
- package/dist/hooks/magic-context/reasoning-budget.d.ts +40 -0
- package/dist/hooks/magic-context/reasoning-budget.d.ts.map +1 -0
- package/dist/hooks/magic-context/reasoning-removal.d.ts +6 -6
- package/dist/hooks/magic-context/reasoning-removal.d.ts.map +1 -1
- package/dist/hooks/magic-context/recomp-orchestrator.d.ts +2 -0
- package/dist/hooks/magic-context/recomp-orchestrator.d.ts.map +1 -1
- package/dist/hooks/magic-context/sentinel.d.ts +2 -0
- package/dist/hooks/magic-context/sentinel.d.ts.map +1 -1
- package/dist/hooks/magic-context/strip-content.d.ts +7 -3
- package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
- package/dist/hooks/magic-context/supersession-reclaim.d.ts +4 -0
- package/dist/hooks/magic-context/supersession-reclaim.d.ts.map +1 -1
- package/dist/hooks/magic-context/tag-messages.d.ts +13 -0
- package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
- package/dist/hooks/magic-context/tail-hygiene-walk.d.ts +5 -0
- package/dist/hooks/magic-context/tail-hygiene-walk.d.ts.map +1 -1
- package/dist/hooks/magic-context/temporal-awareness.d.ts +6 -3
- package/dist/hooks/magic-context/temporal-awareness.d.ts.map +1 -1
- package/dist/hooks/magic-context/temporal-served-projection.d.ts +4 -0
- package/dist/hooks/magic-context/temporal-served-projection.d.ts.map +1 -0
- package/dist/hooks/magic-context/tool-reclaim.d.ts +2 -0
- package/dist/hooks/magic-context/tool-reclaim.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-compartment-phase.d.ts +3 -28
- package/dist/hooks/magic-context/transform-compartment-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +34 -12
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform.d.ts +11 -5
- package/dist/hooks/magic-context/transform.d.ts.map +1 -1
- package/dist/hooks/magic-context/wrapup-orchestrator.d.ts.map +1 -1
- package/dist/{index-fg34g6a5.js → index-1j34a56j.js} +49 -8
- package/dist/index-33gprt9g.js +30 -0
- package/dist/{index-zx63j2e2.js → index-5cep2r9n.js} +3 -2
- package/dist/{index-5pg0acf7.js → index-amycb7b1.js} +1 -1
- package/dist/{index-wgt4gamw.js → index-dr0gepzw.js} +507 -53
- package/dist/{index-1vs6anwz.js → index-n0vnzz6h.js} +2 -1
- package/dist/{index-977gxfz0.js → index-ramz5kkm.js} +1 -1
- package/dist/{index-by6h2pav.js → index-wtb9hzk6.js} +499 -284
- package/dist/{index-3wagyrnj.js → index-x37vg474.js} +5 -1
- package/dist/{index-me3zcj5t.js → index-z2g20msd.js} +4 -8
- package/dist/index.js +1 -1
- package/dist/{message-time-backfill-5ewk0axe.js → message-time-backfill-phrwp2fz.js} +2 -2
- package/dist/{model-resolution-5haaxnpt.js → model-resolution-wazv26n0.js} +1 -1
- package/dist/plugin/rpc-handlers.d.ts +4 -0
- package/dist/plugin/rpc-handlers.d.ts.map +1 -1
- package/dist/{read-session-chunk-apjwrttc.js → read-session-chunk-82rkqa8j.js} +4 -4
- package/dist/{recomp-orchestrator-gyeevxaw.js → recomp-orchestrator-vc5dkzy2.js} +9 -9
- package/dist/{send-session-notification-y29y9fsr.js → send-session-notification-rnc4nrsr.js} +3 -3
- package/dist/shared/auto-search-lifecycle.d.ts +7 -0
- package/dist/shared/auto-search-lifecycle.d.ts.map +1 -0
- package/dist/shared/cache-ttl-display.d.ts +6 -4
- package/dist/shared/cache-ttl-display.d.ts.map +1 -1
- package/dist/shared/harness.d.ts +1 -1
- package/dist/shared/harness.d.ts.map +1 -1
- package/dist/shared/historian-tool-expansions.d.ts +1 -1
- package/dist/shared/historian-tool-expansions.d.ts.map +1 -1
- package/dist/shared/historian-tool-template.d.ts +2 -2
- package/dist/shared/historian-tool-template.d.ts.map +1 -1
- package/dist/shared/model-cache-ttl.d.ts +1 -1
- package/dist/shared/model-cache-ttl.d.ts.map +1 -1
- package/dist/shared/model-resolution.d.ts +6 -3
- package/dist/shared/model-resolution.d.ts.map +1 -1
- package/dist/shared/model-suggestion-retry.d.ts +2 -0
- package/dist/shared/model-suggestion-retry.d.ts.map +1 -1
- package/dist/shared/protected-tools-policy.d.ts +6 -0
- package/dist/shared/protected-tools-policy.d.ts.map +1 -0
- package/dist/shared/provider-output-failure.d.ts +19 -0
- package/dist/shared/provider-output-failure.d.ts.map +1 -0
- package/dist/shared/sqlite.d.ts +14 -1
- package/dist/shared/sqlite.d.ts.map +1 -1
- package/dist/shared/temporal-upgrade-fixture.d.ts +19 -0
- package/dist/shared/temporal-upgrade-fixture.d.ts.map +1 -0
- package/dist/shared/window-geometry.d.ts +4 -0
- package/dist/shared/window-geometry.d.ts.map +1 -1
- package/dist/shared/write-transaction-timing.d.ts +8 -1
- package/dist/shared/write-transaction-timing.d.ts.map +1 -1
- package/dist/tools/ctx-expand/render.d.ts.map +1 -1
- package/dist/tools/ctx-reduce/tools.d.ts +2 -0
- package/dist/tools/ctx-reduce/tools.d.ts.map +1 -1
- package/dist/v2/fold/host-media.d.ts +4 -0
- package/dist/v2/fold/host-media.d.ts.map +1 -1
- package/dist/v2/fold/memory-cache.d.ts +70 -0
- package/dist/v2/fold/memory-cache.d.ts.map +1 -0
- package/dist/v2/fold/native-codec.d.ts +10 -0
- package/dist/v2/fold/native-codec.d.ts.map +1 -0
- package/dist/v2/fold/native-replay.d.ts +58 -0
- package/dist/v2/fold/native-replay.d.ts.map +1 -0
- package/dist/v2/fold/policy.d.ts +24 -0
- package/dist/v2/fold/policy.d.ts.map +1 -0
- package/dist/v2/hidden-child-native.d.ts +7 -0
- package/dist/v2/hidden-child-native.d.ts.map +1 -1
- package/dist/v2/hidden-child-record.d.ts +19 -0
- package/dist/v2/hidden-child-record.d.ts.map +1 -1
- package/dist/v2/hidden-completion.d.ts.map +1 -1
- package/dist/v2/hooks/context.d.ts.map +1 -1
- package/dist/v2/hooks/hidden-child.d.ts +46 -2
- package/dist/v2/hooks/hidden-child.d.ts.map +1 -1
- package/dist/v2/hooks/payload.d.ts.map +1 -1
- package/dist/v2/hooks/store.d.ts.map +1 -1
- package/dist/v2/hooks/tools.d.ts.map +1 -1
- package/dist/v2/hooks/types.d.ts +14 -0
- package/dist/v2/hooks/types.d.ts.map +1 -1
- package/dist/v2/server.js +13226 -11340
- package/dist/v2/store-reader.d.ts +16 -0
- package/dist/v2/store-reader.d.ts.map +1 -1
- package/dist/v2/tool-result.d.ts +8 -0
- package/dist/v2/tool-result.d.ts.map +1 -0
- package/dist/web/api.d.ts +6 -0
- package/dist/web/api.d.ts.map +1 -1
- package/dist/web/context-store.d.ts +13 -0
- package/dist/web/context-store.d.ts.map +1 -1
- package/dist/web/display-path.d.ts +28 -0
- package/dist/web/display-path.d.ts.map +1 -0
- package/dist/web/entry-args.d.ts +33 -0
- package/dist/web/entry-args.d.ts.map +1 -0
- package/dist/web/fixtures.d.ts +41 -0
- package/dist/web/fixtures.d.ts.map +1 -1
- package/dist/web/host-opencode.d.ts +9 -0
- package/dist/web/host-opencode.d.ts.map +1 -1
- package/dist/web/host-pi.d.ts +2 -0
- package/dist/web/host-pi.d.ts.map +1 -1
- package/dist/web/main.d.ts +4 -6
- package/dist/web/main.d.ts.map +1 -1
- package/dist/web/main.js +1477 -130
- package/dist/web/memories.d.ts +18 -2
- package/dist/web/memories.d.ts.map +1 -1
- package/dist/web/message-stats.d.ts +45 -0
- package/dist/web/message-stats.d.ts.map +1 -0
- package/dist/web/ui/index.html +1 -0
- package/dist/web/ui/panel.css +7 -0
- package/dist/web/ui/panel.js +332 -124
- package/dist/web/views.d.ts +73 -9
- package/dist/web/views.d.ts.map +1 -1
- package/dist/{wrapup-orchestrator-z9sqpqjf.js → wrapup-orchestrator-x9xamts2.js} +10 -9
- package/package.json +7 -2
- package/src/config/index.test.ts +257 -126
- package/src/config/index.ts +45 -39
- package/src/config/legacy-harness-blocks.test.ts +78 -0
- package/src/config/legacy-harness-blocks.ts +71 -0
- package/src/config/live-run-config.test.ts +49 -5
- package/src/config/live-run-config.ts +29 -0
- package/src/config/live-snapshot.ts +5 -1
- package/src/config/profiles.ts +1 -1
- package/src/config/project-config-trust-boundary.test.ts +2 -2
- package/src/config/project-security.hostile-matrix.test.ts +51 -65
- package/src/config/project-security.test.ts +6 -1
- package/src/config/project-security.ts +13 -12
- package/src/config/protected-tokens.test.ts +1 -1
- package/src/config/raw-loader.test.ts +29 -352
- package/src/config/raw-loader.ts +17 -406
- package/src/config/removed-config-keys.test.ts +1 -1
- package/src/config/schema/magic-context.test.ts +60 -64
- package/src/config/schema/magic-context.ts +105 -137
- package/src/config/variable.ts +21 -12
- package/src/shared/auto-search-lifecycle.ts +27 -0
- package/src/shared/cache-ttl-display.test.ts +1 -1
- package/src/shared/cache-ttl-display.ts +17 -16
- package/src/shared/harness.ts +1 -1
- package/src/shared/historian-tool-defaults.json +6 -6
- package/src/shared/historian-tool-expansions.ts +65 -8
- package/src/shared/historian-tool-preview-defaults.json +13 -0
- package/src/shared/historian-tool-template.ts +48 -14
- package/src/shared/model-cache-ttl.test.ts +2 -2
- package/src/shared/model-cache-ttl.ts +8 -4
- package/src/shared/model-resolution.test.ts +22 -32
- package/src/shared/model-resolution.ts +14 -19
- package/src/shared/model-suggestion-retry.ts +63 -7
- package/src/shared/protected-tools-policy.ts +25 -0
- package/src/shared/provider-output-failure.ts +176 -0
- package/src/shared/sqlite-acquisition-routing.test.ts +18 -0
- package/src/shared/sqlite.ts +100 -15
- package/src/shared/status-detail-text.test.ts +1 -1
- package/src/shared/status-view.test.ts +1 -1
- package/src/shared/temporal-upgrade-fixture.ts +50 -0
- package/src/shared/window-geometry.ts +10 -0
- package/src/shared/write-transaction-attribution.test.ts +2 -2
- package/src/shared/write-transaction-timing.ts +25 -1
- package/dist/features/magic-context/window-report-ledger.d.ts +0 -70
- package/dist/features/magic-context/window-report-ledger.d.ts.map +0 -1
- package/dist/index-e1q8002h.js +0 -16
- package/src/config/misplaced-agent-model.test.ts +0 -55
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
|
|
4
|
+
import { isRecord } from "./record-type-guard";
|
|
5
|
+
|
|
6
|
+
const MAX_NEAR_ZERO_OUTPUT_TOKENS = 32;
|
|
7
|
+
|
|
8
|
+
interface AssistantCompletionShape {
|
|
9
|
+
createdAt: number;
|
|
10
|
+
finish: string | null;
|
|
11
|
+
error: unknown;
|
|
12
|
+
outputTokens: number | null;
|
|
13
|
+
reasoningTokens: number | null;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** A provider transport failure that arrived as an ordinary assistant completion. */
|
|
17
|
+
export class ProviderOutputFailureError extends Error {
|
|
18
|
+
readonly transient = true;
|
|
19
|
+
|
|
20
|
+
constructor(
|
|
21
|
+
readonly fingerprint: string,
|
|
22
|
+
readonly outputTokens: number,
|
|
23
|
+
readonly reasoningTokens: number,
|
|
24
|
+
responseText: string,
|
|
25
|
+
readonly quotaResetAt?: number,
|
|
26
|
+
) {
|
|
27
|
+
const preview = responseText.trim().replace(/\s+/g, " ").slice(0, 160);
|
|
28
|
+
super(
|
|
29
|
+
quotaResetAt !== undefined
|
|
30
|
+
? `provider quota exhausted until ${new Date(quotaResetAt).toISOString()} (account-pool rate limit)`
|
|
31
|
+
: `provider outage completion (output_tokens=${outputTokens}, reasoning_tokens=${reasoningTokens}): ${JSON.stringify(preview)}`,
|
|
32
|
+
);
|
|
33
|
+
this.name = "ProviderOutputFailureError";
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Concurrent maintenance runs must not share provider health, and a new run
|
|
38
|
+
// must re-probe its configured primary. Nested verify batches inherit the scope.
|
|
39
|
+
const primaryQuotas = new AsyncLocalStorage<Map<string, ProviderOutputFailureError>>();
|
|
40
|
+
|
|
41
|
+
export function withDreamerModelCooldown<T>(run: () => T): T {
|
|
42
|
+
return primaryQuotas.getStore() ? run() : primaryQuotas.run(new Map(), run);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function rememberPrimaryQuota(
|
|
46
|
+
model: string,
|
|
47
|
+
error: unknown,
|
|
48
|
+
): ProviderOutputFailureError | null {
|
|
49
|
+
const quotas = primaryQuotas.getStore();
|
|
50
|
+
if (
|
|
51
|
+
!quotas ||
|
|
52
|
+
model === "primary" ||
|
|
53
|
+
!(error instanceof ProviderOutputFailureError) ||
|
|
54
|
+
error.quotaResetAt === undefined ||
|
|
55
|
+
error.quotaResetAt <= Date.now()
|
|
56
|
+
)
|
|
57
|
+
return null;
|
|
58
|
+
const cached = new ProviderOutputFailureError(
|
|
59
|
+
error.fingerprint,
|
|
60
|
+
error.outputTokens,
|
|
61
|
+
error.reasoningTokens,
|
|
62
|
+
"",
|
|
63
|
+
error.quotaResetAt,
|
|
64
|
+
);
|
|
65
|
+
cached.message = error.message;
|
|
66
|
+
quotas.set(model, cached);
|
|
67
|
+
return error;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function primaryQuotaFailure(model: string): ProviderOutputFailureError | null {
|
|
71
|
+
const quotas = primaryQuotas.getStore();
|
|
72
|
+
const error = quotas?.get(model);
|
|
73
|
+
if (!error) return null;
|
|
74
|
+
if (error.quotaResetAt === undefined || error.quotaResetAt <= Date.now()) {
|
|
75
|
+
quotas?.delete(model);
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
const failure = new ProviderOutputFailureError(
|
|
79
|
+
error.fingerprint,
|
|
80
|
+
error.outputTokens,
|
|
81
|
+
error.reasoningTokens,
|
|
82
|
+
"",
|
|
83
|
+
error.quotaResetAt,
|
|
84
|
+
);
|
|
85
|
+
failure.message = error.message;
|
|
86
|
+
return failure;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** The auth adapter emits this entire notice as assistant text, not a host error.
|
|
90
|
+
* Match the envelope, never a quoted notice inside a real manifest or narration. */
|
|
91
|
+
function quotaResetAt(responseText: string, now: number): number | undefined {
|
|
92
|
+
const notice =
|
|
93
|
+
/^All [1-9]\d* account\(s\) rate-limited for [\w.-]+\. Quota resets in ((?:\d+[hms] ?)+)\. Add more accounts with `opencode auth login` or wait and retry\.$/.exec(
|
|
94
|
+
responseText.trim(),
|
|
95
|
+
);
|
|
96
|
+
if (!notice) return undefined;
|
|
97
|
+
const units: Record<string, number> = { h: 3_600_000, m: 60_000, s: 1_000 };
|
|
98
|
+
const duration = [...notice[1].matchAll(/(\d+)([hms])/g)].reduce(
|
|
99
|
+
(sum, match) => sum + Number(match[1]) * units[match[2]],
|
|
100
|
+
0,
|
|
101
|
+
);
|
|
102
|
+
const resetAt = now + duration;
|
|
103
|
+
return duration > 0 && Number.isSafeInteger(resetAt) && resetAt < 8.64e15 ? resetAt : undefined;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function finiteTokenCount(value: unknown): number | null {
|
|
107
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : null;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function completionShape(value: unknown): AssistantCompletionShape | null {
|
|
111
|
+
if (!isRecord(value)) return null;
|
|
112
|
+
const info = isRecord(value.info) ? value.info : value;
|
|
113
|
+
if (info.role !== "assistant") return null;
|
|
114
|
+
|
|
115
|
+
const time = isRecord(info.time) ? info.time : null;
|
|
116
|
+
const tokens = isRecord(info.tokens) ? info.tokens : null;
|
|
117
|
+
return {
|
|
118
|
+
createdAt: typeof time?.created === "number" ? time.created : 0,
|
|
119
|
+
finish:
|
|
120
|
+
typeof info.finish === "string"
|
|
121
|
+
? info.finish
|
|
122
|
+
: typeof info.finish_reason === "string"
|
|
123
|
+
? info.finish_reason
|
|
124
|
+
: typeof info.finishReason === "string"
|
|
125
|
+
? info.finishReason
|
|
126
|
+
: null,
|
|
127
|
+
error: info.error,
|
|
128
|
+
outputTokens: finiteTokenCount(tokens?.output),
|
|
129
|
+
reasoningTokens: finiteTokenCount(tokens?.reasoning),
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function latestAssistantCompletion(messages: unknown): AssistantCompletionShape | null {
|
|
134
|
+
if (!Array.isArray(messages)) return null;
|
|
135
|
+
let latest: AssistantCompletionShape | null = null;
|
|
136
|
+
for (const message of messages) {
|
|
137
|
+
const completion = completionShape(message);
|
|
138
|
+
if (completion && (!latest || completion.createdAt >= latest.createdAt))
|
|
139
|
+
latest = completion;
|
|
140
|
+
}
|
|
141
|
+
return latest;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* OpenCode can serialize a provider outage as a successful `finish=stop` assistant
|
|
146
|
+
* message. Only classify that shape after manifest validation has already failed:
|
|
147
|
+
* a real manifest remains authoritative regardless of its token counts.
|
|
148
|
+
*/
|
|
149
|
+
export function providerOutputFailureFromInvalidManifest(
|
|
150
|
+
messages: unknown,
|
|
151
|
+
responseText: string,
|
|
152
|
+
now = Date.now(),
|
|
153
|
+
): ProviderOutputFailureError | null {
|
|
154
|
+
const completion = latestAssistantCompletion(messages);
|
|
155
|
+
if (completion?.finish?.toLowerCase() !== "stop") return null;
|
|
156
|
+
if (
|
|
157
|
+
completion.error != null ||
|
|
158
|
+
completion.outputTokens === null ||
|
|
159
|
+
completion.reasoningTokens !== 0
|
|
160
|
+
) {
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const normalized = responseText.trim().replace(/\s+/g, " ").toLowerCase();
|
|
165
|
+
if (!normalized) return null;
|
|
166
|
+
const resetAt = quotaResetAt(responseText, now);
|
|
167
|
+
if (resetAt === undefined && completion.outputTokens > MAX_NEAR_ZERO_OUTPUT_TOKENS) return null;
|
|
168
|
+
const fingerprint = createHash("sha256").update(normalized).digest("hex").slice(0, 16);
|
|
169
|
+
return new ProviderOutputFailureError(
|
|
170
|
+
fingerprint,
|
|
171
|
+
completion.outputTokens,
|
|
172
|
+
completion.reasoningTokens,
|
|
173
|
+
responseText,
|
|
174
|
+
resetAt,
|
|
175
|
+
);
|
|
176
|
+
}
|
|
@@ -4,6 +4,7 @@ import { tmpdir } from "node:os";
|
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import {
|
|
6
6
|
Database,
|
|
7
|
+
SqliteAcquisitionBusyError,
|
|
7
8
|
withAsyncPrivilegedWriter,
|
|
8
9
|
withPrivilegedWriter,
|
|
9
10
|
withSqliteTransformPass,
|
|
@@ -11,6 +12,23 @@ import {
|
|
|
11
12
|
import { startSqliteWriteLocker } from "./sqlite-write-locker-test-support";
|
|
12
13
|
import { createTestTempDirFromPath } from "./test-temp-dir";
|
|
13
14
|
|
|
15
|
+
test("async writer never retries callback acquisition errors after work began", async () => {
|
|
16
|
+
const db = new Database(":memory:");
|
|
17
|
+
db.exec("CREATE TABLE context_privilege_state(id INTEGER PRIMARY KEY, enabled INTEGER)");
|
|
18
|
+
let calls = 0;
|
|
19
|
+
try {
|
|
20
|
+
await expect(
|
|
21
|
+
withAsyncPrivilegedWriter(db, () => {
|
|
22
|
+
calls++;
|
|
23
|
+
throw new SqliteAcquisitionBusyError(new Error("nested BEGIN"));
|
|
24
|
+
}),
|
|
25
|
+
).rejects.toThrow("acquisition remained busy");
|
|
26
|
+
expect(calls).toBe(1);
|
|
27
|
+
} finally {
|
|
28
|
+
db.close();
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
|
|
14
32
|
for (const mode of ["default", "immediate", "exclusive", "literal"] as const) {
|
|
15
33
|
test(`shared SQLite retries ${mode} acquisition before running any writes`, async () => {
|
|
16
34
|
const dir = createTestTempDirFromPath(join(tmpdir(), "mc-routed-acquisition-"));
|
package/src/shared/sqlite.ts
CHANGED
|
@@ -245,6 +245,7 @@ function installTransactionRouting(db: BetterSqlite3.Database, readonly: boolean
|
|
|
245
245
|
configurable: true,
|
|
246
246
|
writable: true,
|
|
247
247
|
value: (sql: string) => {
|
|
248
|
+
if (/^\s*(?:COMMIT|END)\b/i.test(sql)) assertTransformWrite();
|
|
248
249
|
if (/^\s*BEGIN\s+(?:IMMEDIATE|EXCLUSIVE)(?:\s+TRANSACTION)?\s*;?\s*$/i.test(sql)) {
|
|
249
250
|
// A transaction that ended without passing through exec (for
|
|
250
251
|
// example an automatic rollback) must not be timed as this one.
|
|
@@ -556,6 +557,33 @@ interface StatementOwner {
|
|
|
556
557
|
const statementOwners = new WeakMap<Database, StatementOwner>();
|
|
557
558
|
const FIRST_PRUNE_AT = 256;
|
|
558
559
|
|
|
560
|
+
/**
|
|
561
|
+
* Bun's default close (`sqlite3_close_v2`) only releases the native connection
|
|
562
|
+
* once every statement created by prepare() is finalized. The close override
|
|
563
|
+
* in ownPreparedStatement can finalize only statements that are still
|
|
564
|
+
* reachable. Once the garbage collector
|
|
565
|
+
* has marked a one-shot statement dead, its weak reference is already cleared,
|
|
566
|
+
* but the statement is finalized only when its memory is later swept. Until
|
|
567
|
+
* then the closed connection keeps the database, WAL and shared-memory files
|
|
568
|
+
* open, for an unbounded time.
|
|
569
|
+
*
|
|
570
|
+
* `close(true)` finalizes every outstanding statement, reachable or not, and
|
|
571
|
+
* releases the connection immediately. When the caller did not ask for errors
|
|
572
|
+
* and that close fails, fall back to the caller's own close so a teardown path
|
|
573
|
+
* never starts throwing; the fallback can defer the release as before.
|
|
574
|
+
*/
|
|
575
|
+
function closeReleasingStatements(
|
|
576
|
+
close: (...args: unknown[]) => unknown,
|
|
577
|
+
args: unknown[],
|
|
578
|
+
): unknown {
|
|
579
|
+
if (args[0] === true) return close(true);
|
|
580
|
+
try {
|
|
581
|
+
return close(true);
|
|
582
|
+
} catch {
|
|
583
|
+
return close(...args);
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
|
|
559
587
|
function ownPreparedStatement(db: Database, statement: Statement): Statement {
|
|
560
588
|
const finalizable = statement as FinalizableStatement;
|
|
561
589
|
// Node finalizes its statements on close and exposes no finalize() method.
|
|
@@ -579,7 +607,7 @@ function ownPreparedStatement(db: Database, statement: Statement): Statement {
|
|
|
579
607
|
}
|
|
580
608
|
}
|
|
581
609
|
references.clear();
|
|
582
|
-
const result = close
|
|
610
|
+
const result = closeReleasingStatements(close, args);
|
|
583
611
|
if (failure) throw failure;
|
|
584
612
|
return result;
|
|
585
613
|
},
|
|
@@ -617,7 +645,12 @@ export function prepareCachedStatement(db: Database, sql: string): Statement {
|
|
|
617
645
|
|
|
618
646
|
const privilegeDepth = new WeakMap<Database, number>();
|
|
619
647
|
const transformPassScope = new AsyncLocalStorage<
|
|
620
|
-
|
|
648
|
+
| {
|
|
649
|
+
active: boolean;
|
|
650
|
+
remainingWaitMs: number;
|
|
651
|
+
guard?: { assert(): void; remainingMs(): number };
|
|
652
|
+
}
|
|
653
|
+
| undefined
|
|
621
654
|
>();
|
|
622
655
|
const admissionScope = new AsyncLocalStorage<boolean>();
|
|
623
656
|
const backgroundWriterScope = new AsyncLocalStorage<boolean>();
|
|
@@ -655,6 +688,17 @@ export function withoutSqliteTransformPass<T>(operation: () => T): T {
|
|
|
655
688
|
return transformPassScope.run(undefined, operation);
|
|
656
689
|
}
|
|
657
690
|
|
|
691
|
+
/** Attach the adapter's existing generation/cancellation/deadline guard to writes. */
|
|
692
|
+
export function guardSqliteTransformPass(guard: { assert(): void; remainingMs(): number }): void {
|
|
693
|
+
const lease = transformPassScope.getStore();
|
|
694
|
+
if (lease) lease.guard = guard;
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
/** Check the attached generation/cancellation/deadline guard before SQL or cache publication. */
|
|
698
|
+
export function assertTransformWrite(): void {
|
|
699
|
+
if (!backgroundWriterScope.getStore()) transformPassScope.getStore()?.guard?.assert();
|
|
700
|
+
}
|
|
701
|
+
|
|
658
702
|
/** Bun names SQLite codes; node:sqlite exposes the numeric (possibly extended) errcode. */
|
|
659
703
|
export function isTransientSqliteError(error: unknown): boolean {
|
|
660
704
|
if (!error || typeof error !== "object") return false;
|
|
@@ -698,6 +742,7 @@ interface WriterAcquisition {
|
|
|
698
742
|
startedAt: number;
|
|
699
743
|
attempts: number;
|
|
700
744
|
claimed: boolean;
|
|
745
|
+
remainingMs?: () => number;
|
|
701
746
|
}
|
|
702
747
|
|
|
703
748
|
/** A write transaction whose BEGIN went through `acquireShort` and has not ended yet. */
|
|
@@ -724,6 +769,7 @@ function foregroundWaitLease() {
|
|
|
724
769
|
* native API cannot separate lock waiting from statement execution. Exhaustion
|
|
725
770
|
* switches to zero-wait acquisition, not a refusal when the writer is free. */
|
|
726
771
|
function withAutocommitTimeout<T>(db: Database, operation: () => T): T {
|
|
772
|
+
assertTransformWrite();
|
|
727
773
|
const lease = foregroundWaitLease();
|
|
728
774
|
if (isInTransaction(db) || (!lease && !backgroundWriterScope.getStore())) return operation();
|
|
729
775
|
const previous = pragmaNumber(db, "busy_timeout");
|
|
@@ -749,6 +795,7 @@ function withAutocommitTimeout<T>(db: Database, operation: () => T): T {
|
|
|
749
795
|
|
|
750
796
|
/** The connection is never handed back to another caller with a shortened timeout. */
|
|
751
797
|
function acquireShort(db: Database, acquire: () => unknown, site: string): void {
|
|
798
|
+
assertTransformWrite();
|
|
752
799
|
const started = performance.now();
|
|
753
800
|
const previous = pragmaNumber(db, "busy_timeout");
|
|
754
801
|
const outer = writerAcquisitionScope.getStore();
|
|
@@ -763,7 +810,12 @@ function acquireShort(db: Database, acquire: () => unknown, site: string): void
|
|
|
763
810
|
// stays short. An ordinary BEGIN inside a transform pass cannot yield;
|
|
764
811
|
// give that single attempt enough time for a brief writer to finish.
|
|
765
812
|
const lease = foregroundWaitLease();
|
|
766
|
-
const timeout =
|
|
813
|
+
const timeout = Math.floor(
|
|
814
|
+
Math.min(
|
|
815
|
+
lease ? lease.remainingWaitMs : SHORT_BUSY_TIMEOUT_MS,
|
|
816
|
+
owner?.remainingMs?.() ?? lease?.guard?.remainingMs() ?? Infinity,
|
|
817
|
+
),
|
|
818
|
+
);
|
|
767
819
|
db.exec(`PRAGMA busy_timeout=${timeout}`);
|
|
768
820
|
acquire();
|
|
769
821
|
acquiredAt = performance.now();
|
|
@@ -871,11 +923,28 @@ export async function beginSqliteWriterAsync(db: Database, site: string): Promis
|
|
|
871
923
|
}
|
|
872
924
|
|
|
873
925
|
/** Retry admission before any turn work, yielding between short lock attempts. */
|
|
874
|
-
export async function withAsyncPrivilegedWriter<T>(
|
|
926
|
+
export async function withAsyncPrivilegedWriter<T>(
|
|
927
|
+
db: Database,
|
|
928
|
+
operation: () => T,
|
|
929
|
+
options: {
|
|
930
|
+
signal?: AbortSignal;
|
|
931
|
+
beforeRetry?: (error: SqliteAcquisitionBusyError) => void;
|
|
932
|
+
jitter?: boolean;
|
|
933
|
+
budgetMs?: number;
|
|
934
|
+
assertCurrentPass?: () => void;
|
|
935
|
+
} = {},
|
|
936
|
+
): Promise<T> {
|
|
875
937
|
const started = performance.now();
|
|
938
|
+
const budgetMs = Math.max(
|
|
939
|
+
0,
|
|
940
|
+
Math.min(FOREGROUND_ACQUISITION_BUDGET_MS, options.budgetMs ?? Infinity),
|
|
941
|
+
);
|
|
876
942
|
let attempts = 0;
|
|
877
943
|
for (;;) {
|
|
944
|
+
options.signal?.throwIfAborted();
|
|
945
|
+
options.assertCurrentPass?.();
|
|
878
946
|
attempts++;
|
|
947
|
+
let entered = false;
|
|
879
948
|
try {
|
|
880
949
|
const acquisition: WriterAcquisition = {
|
|
881
950
|
site: "privileged_writer",
|
|
@@ -883,35 +952,51 @@ export async function withAsyncPrivilegedWriter<T>(db: Database, operation: () =
|
|
|
883
952
|
startedAt: started,
|
|
884
953
|
attempts,
|
|
885
954
|
claimed: false,
|
|
955
|
+
remainingMs: () => Math.max(0, budgetMs - (performance.now() - started)),
|
|
886
956
|
};
|
|
887
957
|
// The acquisition and hold of this transaction are reported when it
|
|
888
958
|
// commits or rolls back (see endWriterTransaction).
|
|
889
959
|
return admissionScope.run(true, () =>
|
|
890
960
|
withSqliteTransformPass(() =>
|
|
891
961
|
writerAcquisitionScope.run(acquisition, () =>
|
|
892
|
-
withPrivilegedWriter(db,
|
|
962
|
+
withPrivilegedWriter(db, () => {
|
|
963
|
+
entered = true;
|
|
964
|
+
return operation();
|
|
965
|
+
}),
|
|
893
966
|
),
|
|
894
967
|
),
|
|
895
968
|
);
|
|
896
969
|
} catch (error) {
|
|
897
970
|
// A callback failure can occur after writes; only retry a failed BEGIN.
|
|
898
|
-
if (!(error instanceof SqliteAcquisitionBusyError)) throw error;
|
|
971
|
+
if (entered || !(error instanceof SqliteAcquisitionBusyError)) throw error;
|
|
972
|
+
// Adapters may serve a validated saved request instead of waiting.
|
|
973
|
+
// This runs only after a failed BEGIN, never after callback writes.
|
|
974
|
+
options.beforeRetry?.(error);
|
|
899
975
|
const elapsed = performance.now() - started;
|
|
900
|
-
if (elapsed >=
|
|
976
|
+
if (elapsed >= budgetMs) {
|
|
901
977
|
reportSqliteDiagnostic(
|
|
902
978
|
`sqlite writer site=privileged_writer lane=foreground acquire_ms=${Math.round(elapsed)} attempts=${attempts} outcome=busy`,
|
|
903
979
|
);
|
|
904
980
|
throw error;
|
|
905
981
|
}
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
attempts === 1 ? 500 : 1000,
|
|
911
|
-
FOREGROUND_ACQUISITION_BUDGET_MS - elapsed,
|
|
912
|
-
),
|
|
913
|
-
),
|
|
982
|
+
const backoff = attempts === 1 ? 500 : 1000;
|
|
983
|
+
const delay = Math.min(
|
|
984
|
+
options.jitter ? backoff * (0.8 + Math.random() * 0.4) : backoff,
|
|
985
|
+
budgetMs - elapsed,
|
|
914
986
|
);
|
|
987
|
+
await new Promise<void>((resolve, reject) => {
|
|
988
|
+
const abort = () => {
|
|
989
|
+
clearTimeout(timer);
|
|
990
|
+
options.signal?.removeEventListener("abort", abort);
|
|
991
|
+
reject(options.signal?.reason ?? new Error("Writer wait aborted"));
|
|
992
|
+
};
|
|
993
|
+
const timer = setTimeout(() => {
|
|
994
|
+
options.signal?.removeEventListener("abort", abort);
|
|
995
|
+
resolve();
|
|
996
|
+
}, delay);
|
|
997
|
+
options.signal?.addEventListener("abort", abort, { once: true });
|
|
998
|
+
if (options.signal?.aborted) abort();
|
|
999
|
+
});
|
|
915
1000
|
}
|
|
916
1001
|
}
|
|
917
1002
|
}
|
|
@@ -92,7 +92,7 @@ describe("status detail text", () => {
|
|
|
92
92
|
expect(formatStatusDetailMarkdown(STATUS_FIXTURE)).toBe(`## Magic Context Status
|
|
93
93
|
|
|
94
94
|
- **Context:** 75.0% of usable context (96,000 / 128,000 tokens)
|
|
95
|
-
- **Cache lifetime:** 1h (config
|
|
95
|
+
- **Cache lifetime:** 1h (your config)
|
|
96
96
|
- **Automatic compression:** at 65.0% of usable context
|
|
97
97
|
- **History compression:** Compressing history · 12 history blocks
|
|
98
98
|
- **Reclaimable:** 3 spent tool outputs (~14k tokens)
|
|
@@ -256,7 +256,7 @@ describe("status view model", () => {
|
|
|
256
256
|
* gap fit; otherwise the caller draws one column.
|
|
257
257
|
*/
|
|
258
258
|
test("draws two columns only when both columns' values fit", () => {
|
|
259
|
-
const sections = view().sections;
|
|
259
|
+
const sections = view({ cacheTtlSource: "default" }).sections;
|
|
260
260
|
for (const section of sections) {
|
|
261
261
|
const longest = Math.max(...section.rows.map((row) => row.value.length));
|
|
262
262
|
expect(statusSectionWidth(section)).toBe(section.labelWidth + 1 + longest);
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import fixture from "../../../../testdata/temporal-upgrade-projections.json";
|
|
2
|
+
import type { Database } from "./sqlite";
|
|
3
|
+
|
|
4
|
+
export type TemporalFixtureRuntime = "Pi" | "OpenCode 1" | "OpenCode 2";
|
|
5
|
+
type Value = null | string | number | { base64: string };
|
|
6
|
+
interface CapturedSession {
|
|
7
|
+
sessionId: string;
|
|
8
|
+
cwd?: string;
|
|
9
|
+
input: unknown[];
|
|
10
|
+
entryIds?: string[];
|
|
11
|
+
projection: unknown[];
|
|
12
|
+
projectionJson: string;
|
|
13
|
+
state: Record<string, Array<Record<string, Value>>>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const temporalUpgradeCases: Record<TemporalFixtureRuntime, CapturedSession> = fixture.cases;
|
|
17
|
+
|
|
18
|
+
/** Restore old served state, never by first rendering it with the current code. */
|
|
19
|
+
export function seedTemporalUpgradeFixture(
|
|
20
|
+
db: Database,
|
|
21
|
+
runtime: TemporalFixtureRuntime,
|
|
22
|
+
): CapturedSession {
|
|
23
|
+
const captured = temporalUpgradeCases[runtime];
|
|
24
|
+
db.transaction(() => {
|
|
25
|
+
for (const [table, rows] of Object.entries(captured.state)) {
|
|
26
|
+
for (const row of rows) {
|
|
27
|
+
const columns = Object.keys(row);
|
|
28
|
+
const values = Object.values(row).map((value) =>
|
|
29
|
+
value !== null && typeof value === "object"
|
|
30
|
+
? Buffer.from(value.base64, "base64")
|
|
31
|
+
: value,
|
|
32
|
+
);
|
|
33
|
+
db.prepare(
|
|
34
|
+
`INSERT INTO ${table} (${columns.join(",")}) VALUES (${columns.map(() => "?").join(",")})`,
|
|
35
|
+
).run(...values);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// Advance only the cache clock: timestamp-derived marker bytes and
|
|
39
|
+
// the old input/projection are the immutable captured fixture.
|
|
40
|
+
db.prepare("UPDATE session_meta SET last_response_time=? WHERE session_id=?").run(
|
|
41
|
+
Date.now(),
|
|
42
|
+
captured.sessionId,
|
|
43
|
+
);
|
|
44
|
+
db.prepare("UPDATE lkg_slots SET captured_at=? WHERE session_id=?").run(
|
|
45
|
+
Date.now(),
|
|
46
|
+
captured.sessionId,
|
|
47
|
+
);
|
|
48
|
+
}).immediate();
|
|
49
|
+
return captured;
|
|
50
|
+
}
|
|
@@ -89,6 +89,8 @@ export interface WindowDerivation {
|
|
|
89
89
|
geometry: WindowGeometry;
|
|
90
90
|
windowSource: WindowLimitSource;
|
|
91
91
|
absoluteWall: number;
|
|
92
|
+
/** Accepted provider input used to raise the usable denominator above metadata. */
|
|
93
|
+
provenInputTokens?: number;
|
|
92
94
|
}
|
|
93
95
|
|
|
94
96
|
export interface WindowGeometryResult {
|
|
@@ -691,6 +693,7 @@ export function applyProvenInputFloor(
|
|
|
691
693
|
absoluteWall: trustedAbsoluteWall
|
|
692
694
|
? geometry.derivation.absoluteWall
|
|
693
695
|
: Math.max(geometry.derivation.absoluteWall, provenInputTokens),
|
|
696
|
+
provenInputTokens,
|
|
694
697
|
},
|
|
695
698
|
},
|
|
696
699
|
};
|
|
@@ -715,6 +718,13 @@ export function formatWindowDerivationLine(
|
|
|
715
718
|
return `${formatCompactTokens(inputTokens)} / ${formatCompactTokens(result.usableSoft)} usable · window ${formatCompactTokens(result.derivation.window)} · ${formatCompactTokens(result.derivation.reserve)} ${reserveLabel}`;
|
|
716
719
|
}
|
|
717
720
|
|
|
721
|
+
/** Distinguish metadata from a denominator raised by an accepted input measurement. */
|
|
722
|
+
export function formatWindowSource(result: WindowGeometryResult | undefined): string {
|
|
723
|
+
return result?.derivation.provenInputTokens
|
|
724
|
+
? `provider-measured floor (${result.derivation.windowSource})`
|
|
725
|
+
: (result?.derivation.windowSource ?? "unknown");
|
|
726
|
+
}
|
|
727
|
+
|
|
718
728
|
export function formatCompactTokens(value: number): string {
|
|
719
729
|
if (Math.abs(value) >= 1_000_000) {
|
|
720
730
|
return `${(value / 1_000_000).toFixed(1).replace(/\.0$/, "")}m`;
|
|
@@ -70,7 +70,7 @@ const fencedSources: Array<{ path: string; sites: string[]; reporterCalls?: stri
|
|
|
70
70
|
},
|
|
71
71
|
{
|
|
72
72
|
path: "packages/pi-plugin/src/context-handler.ts",
|
|
73
|
-
sites: ["
|
|
73
|
+
sites: ["pi_fallback_adoption"],
|
|
74
74
|
},
|
|
75
75
|
];
|
|
76
76
|
|
|
@@ -116,7 +116,7 @@ const newlyCoveredSites = [
|
|
|
116
116
|
"pi_materialize_cache",
|
|
117
117
|
"pi_soft_refresh_cache",
|
|
118
118
|
"pi_historian_publish",
|
|
119
|
-
"
|
|
119
|
+
"pi_fallback_adoption",
|
|
120
120
|
"user_memory_candidate_insert",
|
|
121
121
|
] as const;
|
|
122
122
|
|
|
@@ -15,12 +15,36 @@ export function logSlowWriteTransaction(
|
|
|
15
15
|
startedAt: number,
|
|
16
16
|
thresholdMs = SLOW_WRITE_TRANSACTION_THRESHOLD_MS,
|
|
17
17
|
completedAtMs = performance.now(),
|
|
18
|
+
steps?: Readonly<Record<string, number>>,
|
|
18
19
|
): void {
|
|
19
20
|
try {
|
|
20
21
|
const durationMs = completedAtMs - startedAt;
|
|
21
22
|
if (durationMs < thresholdMs) return;
|
|
22
|
-
|
|
23
|
+
const detail = steps
|
|
24
|
+
? Object.entries(steps)
|
|
25
|
+
.map(([name, ms]) => `${name}=${ms.toFixed(1)}ms`)
|
|
26
|
+
.join(" ")
|
|
27
|
+
: "";
|
|
28
|
+
log(
|
|
29
|
+
`[magic-context] slow write transaction: site=${site} held=${durationMs.toFixed(1)}ms${detail ? ` ${detail}` : ""}`,
|
|
30
|
+
);
|
|
23
31
|
} catch {
|
|
24
32
|
// Timing diagnostics must never make a committed write appear to fail.
|
|
25
33
|
}
|
|
26
34
|
}
|
|
35
|
+
|
|
36
|
+
/** Step durations include precomputation when named `pre_*`; held time never does. */
|
|
37
|
+
export class WriteTransactionSteps {
|
|
38
|
+
readonly durations: Record<string, number> = {};
|
|
39
|
+
private last = performance.now();
|
|
40
|
+
|
|
41
|
+
mark(name: string): void {
|
|
42
|
+
const now = performance.now();
|
|
43
|
+
this.durations[name] = now - this.last;
|
|
44
|
+
this.last = now;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
reset(): void {
|
|
48
|
+
this.last = performance.now();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import type { ContextLimitProvenance } from "../../shared/context-limit-provenance";
|
|
2
|
-
export declare const WINDOW_REPORTS_ROTATION_BYTES: number;
|
|
3
|
-
/**
|
|
4
|
-
* Fusiform's full-catalog dual-detector admit sweep (pm_d3e23fcd, 2026-08-13:
|
|
5
|
-
* 125 providers / 5,680 models whose catalogs carry other vendors' models).
|
|
6
|
-
* An ADMIT list, not a classification — membership warrants
|
|
7
|
-
* `path_may_forward: true` at capture; absence clears nobody (a provider
|
|
8
|
-
* using an id convention neither detector knows is silently missing here),
|
|
9
|
-
* which is why the emitter never writes `false`: the report schema pins
|
|
10
|
-
* absent = unknown routing (refuses promotion, same as true), while an
|
|
11
|
-
* explicit false would PERMIT promotion — a claim this set structurally
|
|
12
|
-
* cannot support.
|
|
13
|
-
*
|
|
14
|
-
* `ollama-cloud` is deliberately EXCLUDED: the detectors admit it (it
|
|
15
|
-
* carries glm/deepseek/kimi weights) but it imposes its OWN wall from its
|
|
16
|
-
* own serving stack — and this field marks whose-wall-might-fire, not
|
|
17
|
-
* who-carries-whose-models. Other own-wall gateways may hide in this list;
|
|
18
|
-
* only per-cell evidence distinguishes them, and Fusiform's adjudicator
|
|
19
|
-
* refuses promotion for every admitted provider regardless, so a wrong
|
|
20
|
-
* `true` here degrades toward refusal, never toward a wrong mint.
|
|
21
|
-
*/
|
|
22
|
-
export declare const FORWARDING_PROVIDER_IDS: ReadonlySet<string>;
|
|
23
|
-
export interface WindowReport {
|
|
24
|
-
provider_id?: string;
|
|
25
|
-
model_id?: string;
|
|
26
|
-
access_path: "api";
|
|
27
|
-
status?: number;
|
|
28
|
-
matched_pattern?: string;
|
|
29
|
-
extracted_limit?: number;
|
|
30
|
-
extracted_limit_units?: "provider";
|
|
31
|
-
attempted_tokens?: number;
|
|
32
|
-
attempted_tokens_units?: "estimate";
|
|
33
|
-
geometry: "prompt_only" | "combined" | "unknown";
|
|
34
|
-
observed_at_ms: number;
|
|
35
|
-
largest_success?: number;
|
|
36
|
-
largest_success_units?: "estimate";
|
|
37
|
-
/**
|
|
38
|
-
* Emitted ONLY as `true` (provider is a known forwarder) or omitted
|
|
39
|
-
* (unknown routing — refuses promotion by the schema's absent rule).
|
|
40
|
-
* Never `false`: this reporter has no evidence basis for asserting a
|
|
41
|
-
* path cannot forward, and explicit false is the one value that would
|
|
42
|
-
* permit promoting a measured report at a forwarded key.
|
|
43
|
-
*/
|
|
44
|
-
path_may_forward?: true;
|
|
45
|
-
/** Observed routing evidence only; never inferred from provider configuration. */
|
|
46
|
-
served_by_hint?: string;
|
|
47
|
-
}
|
|
48
|
-
export interface AppendWindowReportInput {
|
|
49
|
-
db: import("../../shared/sqlite").Database;
|
|
50
|
-
providerID?: string;
|
|
51
|
-
modelID?: string;
|
|
52
|
-
matchedPattern?: string;
|
|
53
|
-
reportedLimit?: number;
|
|
54
|
-
reportedLimitProvenance?: ContextLimitProvenance;
|
|
55
|
-
attemptedTokens?: number;
|
|
56
|
-
error?: unknown;
|
|
57
|
-
observedAtMs?: number;
|
|
58
|
-
sessionID?: string;
|
|
59
|
-
}
|
|
60
|
-
export interface WindowReportLedgerDiagnostics {
|
|
61
|
-
swallowedWriteCount: number;
|
|
62
|
-
lastErrorMessage: string | null;
|
|
63
|
-
}
|
|
64
|
-
export declare function getWindowReportsPath(): string;
|
|
65
|
-
export declare function getWindowReportLedgerDiagnostics(): WindowReportLedgerDiagnostics;
|
|
66
|
-
export declare function __resetWindowReportLedgerDiagnosticsForTests(): void;
|
|
67
|
-
export declare function buildWindowReport(input: AppendWindowReportInput): WindowReport;
|
|
68
|
-
export declare function appendWindowReport(report: WindowReport): void;
|
|
69
|
-
export declare function captureWindowReport(input: AppendWindowReportInput): void;
|
|
70
|
-
//# sourceMappingURL=window-report-ledger.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"window-report-ledger.d.ts","sourceRoot":"","sources":["../../../src/features/magic-context/window-report-ledger.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AASpF,eAAO,MAAM,6BAA6B,QAAmB,CAAC;AAE9D;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,uBAAuB,EAAE,WAAW,CAAC,MAAM,CA6HtD,CAAC;AAEH,MAAM,WAAW,YAAY;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,KAAK,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,qBAAqB,CAAC,EAAE,UAAU,CAAC;IACnC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,sBAAsB,CAAC,EAAE,UAAU,CAAC;IACpC,QAAQ,EAAE,aAAa,GAAG,UAAU,GAAG,SAAS,CAAC;IACjD,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,qBAAqB,CAAC,EAAE,UAAU,CAAC;IACnC;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,IAAI,CAAC;IACxB,kFAAkF;IAClF,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,uBAAuB;IACpC,EAAE,EAAE,OAAO,qBAAqB,EAAE,QAAQ,CAAC;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uBAAuB,CAAC,EAAE,sBAAsB,CAAC;IACjD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,6BAA6B;IAC1C,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAKD,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAYD,wBAAgB,gCAAgC,IAAI,6BAA6B,CAEhF;AAED,wBAAgB,4CAA4C,IAAI,IAAI,CAGnE;AA2ED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,uBAAuB,GAAG,YAAY,CAqC9E;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAmB7D;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,uBAAuB,GAAG,IAAI,CAMxE"}
|
package/dist/index-e1q8002h.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
log
|
|
3
|
-
} from "./index-qbkzdkk0.js";
|
|
4
|
-
|
|
5
|
-
// src/shared/write-transaction-timing.ts
|
|
6
|
-
var SLOW_WRITE_TRANSACTION_THRESHOLD_MS = 1000;
|
|
7
|
-
function logSlowWriteTransaction(site, startedAt, thresholdMs = SLOW_WRITE_TRANSACTION_THRESHOLD_MS, completedAtMs = performance.now()) {
|
|
8
|
-
try {
|
|
9
|
-
const durationMs = completedAtMs - startedAt;
|
|
10
|
-
if (durationMs < thresholdMs)
|
|
11
|
-
return;
|
|
12
|
-
log(`[magic-context] slow write transaction: site=${site} held=${durationMs.toFixed(1)}ms`);
|
|
13
|
-
} catch {}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export { logSlowWriteTransaction };
|