@iderouter/index-mcp 0.2.0-beta.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.
Files changed (69) hide show
  1. package/README.md +93 -0
  2. package/package.json +26 -0
  3. package/scripts/benchmark-all.mjs +177 -0
  4. package/scripts/benchmark-auto-continuation.mjs +188 -0
  5. package/scripts/benchmark-background-fine-resume.mjs +245 -0
  6. package/scripts/benchmark-background-fine-wait.mjs +76 -0
  7. package/scripts/benchmark-background-fine.mjs +132 -0
  8. package/scripts/benchmark-clean-snapshot.mjs +83 -0
  9. package/scripts/benchmark-coarse-ready-search.mjs +161 -0
  10. package/scripts/benchmark-deferred.mjs +62 -0
  11. package/scripts/benchmark-first-semantic-visible.mjs +151 -0
  12. package/scripts/benchmark-gate.mjs +107 -0
  13. package/scripts/benchmark-generic-resumed-single-chunk-embed.mjs +104 -0
  14. package/scripts/benchmark-noop.mjs +24 -0
  15. package/scripts/benchmark-priority-ready-search.mjs +165 -0
  16. package/scripts/benchmark-repeat-search.mjs +148 -0
  17. package/scripts/benchmark-resumed-retry-burst.mjs +187 -0
  18. package/scripts/benchmark-resumed-single-chunk-success.mjs +154 -0
  19. package/scripts/benchmark-resumed-single-chunk.mjs +146 -0
  20. package/scripts/benchmark-single-priority-chunk-embed.mjs +145 -0
  21. package/scripts/benchmark-small-change.mjs +146 -0
  22. package/scripts/benchmark-stage-summary.mjs +88 -0
  23. package/scripts/lib/auto-continuation-state.mjs +34 -0
  24. package/scripts/lib/benchmark-query-packs.mjs +123 -0
  25. package/scripts/lib/benchmark-snapshot.mjs +109 -0
  26. package/scripts/lib/mcp-bench.mjs +455 -0
  27. package/src/architecture-query-fallback.js +50 -0
  28. package/src/background-definition-chunks.js +199 -0
  29. package/src/background-embedding-profile.js +64 -0
  30. package/src/background-fine-budget.js +18 -0
  31. package/src/background-fine-runtime.js +179 -0
  32. package/src/background-fine-selection.js +332 -0
  33. package/src/checkpoint-policy.js +16 -0
  34. package/src/conflict-policy.js +17 -0
  35. package/src/deferred-retry-delay.js +14 -0
  36. package/src/deferred-retry-status.js +10 -0
  37. package/src/embedding-attempt-ordinal.js +17 -0
  38. package/src/embedding-failure-penalty.js +60 -0
  39. package/src/embedding-failure-policy.js +52 -0
  40. package/src/embedding-flush-timeout.js +33 -0
  41. package/src/embedding-inflight-status.js +18 -0
  42. package/src/embedding-model-policy.js +44 -0
  43. package/src/embedding-next-switch.js +18 -0
  44. package/src/embedding-request-status-detail.js +25 -0
  45. package/src/embedding-request-status.js +22 -0
  46. package/src/embedding-selection-order.js +23 -0
  47. package/src/fine-run-queue.js +14 -0
  48. package/src/index.js +7970 -0
  49. package/src/job-supersession.js +25 -0
  50. package/src/priority-progress.js +20 -0
  51. package/src/priority-ready-anchor-coverage-normalize.js +18 -0
  52. package/src/priority-ready-anchor-coverage.js +23 -0
  53. package/src/priority-ready-hotspots.js +344 -0
  54. package/src/priority-ready-status.js +30 -0
  55. package/src/priority-ready-targets.js +45 -0
  56. package/src/priority-usable-attempt-plan.js +44 -0
  57. package/src/priority-usable-attempt-timeout.js +18 -0
  58. package/src/priority-usable-fast-path.js +11 -0
  59. package/src/priority-usable-probe-order.js +34 -0
  60. package/src/remote-strategy-failure-cache.js +55 -0
  61. package/src/resume-seed.js +9 -0
  62. package/src/semantic-first-checkpoint.js +8 -0
  63. package/src/semantic-slow-path.js +10 -0
  64. package/src/single-chunk-attempt-timeout.js +13 -0
  65. package/src/single-chunk-embedding-content.js +26 -0
  66. package/src/single-chunk-embedding-policy.js +18 -0
  67. package/src/single-chunk-provider-order.js +12 -0
  68. package/src/single-chunk-provider-policy.js +63 -0
  69. package/src/worker-lock-retry.js +24 -0
@@ -0,0 +1,60 @@
1
+ export function recordEmbeddingFailurePenalty({
2
+ state = null,
3
+ model = "",
4
+ source = "",
5
+ message = "",
6
+ nowMs = Date.now(),
7
+ }) {
8
+ const next = state && typeof state === "object" ? { ...state } : {};
9
+ const key = String(model || "").trim();
10
+ if (!key) return next;
11
+ next[key] = {
12
+ model: key,
13
+ source: String(source || "").trim(),
14
+ message: String(message || "").trim(),
15
+ failedAt: Number(nowMs || 0),
16
+ };
17
+ return next;
18
+ }
19
+
20
+ export function activeEmbeddingFailurePenalty({
21
+ state = null,
22
+ model = "",
23
+ nowMs = Date.now(),
24
+ cooldownMs = 0,
25
+ }) {
26
+ const key = String(model || "").trim();
27
+ if (!key || !state || typeof state !== "object") return null;
28
+ const entry = state[key];
29
+ if (!entry) return null;
30
+ const failedAt = Number(entry.failedAt || 0);
31
+ const cooldown = Math.max(0, Number(cooldownMs || 0));
32
+ if (!failedAt || !cooldown) return null;
33
+ if (Number(nowMs || 0) - failedAt >= cooldown) return null;
34
+ return entry;
35
+ }
36
+
37
+ export function clearEmbeddingFailurePenalty({
38
+ state = null,
39
+ model = "",
40
+ }) {
41
+ const key = String(model || "").trim();
42
+ if (!key || !state || typeof state !== "object" || !state[key]) return state;
43
+ const next = { ...state };
44
+ delete next[key];
45
+ return next;
46
+ }
47
+
48
+ export function hasActiveEmbeddingFailurePenalty({
49
+ state = null,
50
+ model = "",
51
+ nowMs = Date.now(),
52
+ cooldownMs = 0,
53
+ }) {
54
+ return Boolean(activeEmbeddingFailurePenalty({
55
+ state,
56
+ model,
57
+ nowMs,
58
+ cooldownMs,
59
+ }));
60
+ }
@@ -0,0 +1,52 @@
1
+ export function isEmbeddingAuthenticationError(error) {
2
+ const message = error instanceof Error ? error.message : String(error || "");
3
+ const lower = message.toLowerCase();
4
+ return lower.includes("401 unauthorized") ||
5
+ lower.includes("invalid token") ||
6
+ lower.includes("invalid api key") ||
7
+ lower.includes("incorrect api key");
8
+ }
9
+
10
+ export function isRetryableEmbeddingOutageError(error) {
11
+ const message = error instanceof Error ? error.message : String(error || "");
12
+ const lower = message.toLowerCase();
13
+ if (isEmbeddingAuthenticationError(message)) return false;
14
+ return lower.includes("embedding request failed") ||
15
+ lower.includes("embedding chunk flush timed out") ||
16
+ lower.includes("service_unavailable") ||
17
+ lower.includes("request_failed") ||
18
+ lower.includes("/embeddings");
19
+ }
20
+
21
+ export function shouldDegradeToCoarseOnEmbeddingFailure({
22
+ coarseReady = false,
23
+ priorityFineReady = false,
24
+ error,
25
+ }) {
26
+ if (!coarseReady) return false;
27
+ if (priorityFineReady) return false;
28
+ return isEmbeddingAuthenticationError(error);
29
+ }
30
+
31
+ export function shouldDegradeToCoarseFromState({
32
+ job = null,
33
+ index = null,
34
+ error,
35
+ }) {
36
+ return shouldDegradeToCoarseOnEmbeddingFailure({
37
+ coarseReady: Boolean(job?.coarseReady || index?.coarseReady),
38
+ priorityFineReady: Boolean(job?.priorityFineReady || index?.priorityFineReady),
39
+ error,
40
+ });
41
+ }
42
+
43
+ export function shouldDeferSemanticRetryFromState({
44
+ job = null,
45
+ index = null,
46
+ error,
47
+ }) {
48
+ const coarseReady = Boolean(job?.coarseReady || index?.coarseReady);
49
+ const priorityFineReady = Boolean(job?.priorityFineReady || index?.priorityFineReady);
50
+ if (!coarseReady || priorityFineReady) return false;
51
+ return isRetryableEmbeddingOutageError(error);
52
+ }
@@ -0,0 +1,33 @@
1
+ export function embeddingFlushTimeoutMs({
2
+ source = "",
3
+ requestTimeoutMs = 0,
4
+ priorityTimeoutMs = 0,
5
+ priorityFallbackTimeoutMs = 0,
6
+ }) {
7
+ const sourceText = String(source || "");
8
+ const requestMs = Math.max(0, Number(requestTimeoutMs || 0));
9
+ const priorityMs = Math.max(0, Number(priorityTimeoutMs || 0));
10
+ const priorityFallbackMs = Math.max(0, Number(priorityFallbackTimeoutMs || 0));
11
+
12
+ if (sourceText.startsWith("priority_usable_strategy_fallback")) {
13
+ return Math.max(
14
+ Math.min(
15
+ Math.max(requestMs, priorityFallbackMs),
16
+ priorityFallbackMs,
17
+ ),
18
+ priorityFallbackMs,
19
+ );
20
+ }
21
+
22
+ if (sourceText.startsWith("priority_usable_strategy")) {
23
+ return Math.max(
24
+ Math.min(
25
+ Math.max(requestMs, priorityMs),
26
+ Math.max(priorityMs, 24000),
27
+ ),
28
+ priorityMs,
29
+ );
30
+ }
31
+
32
+ return Math.max(requestMs * 2, priorityMs);
33
+ }
@@ -0,0 +1,18 @@
1
+ export function shouldAnnotateEmbeddingInFlight({
2
+ jobStatus = "",
3
+ currentStep = "",
4
+ totalChunks = 0,
5
+ embeddedCount = 0,
6
+ batchStartedAt = "",
7
+ updatedAt = "",
8
+ slowThresholdMs = 15000,
9
+ nowMs = Date.now(),
10
+ }) {
11
+ if (String(jobStatus || "") !== "indexing") return false;
12
+ if (!String(currentStep || "").toLowerCase().includes("embedding batch")) return false;
13
+ if (Number(totalChunks || 0) <= 0) return false;
14
+ if (Number(embeddedCount || 0) > 0) return false;
15
+ const startedMs = Date.parse(String(batchStartedAt || updatedAt || ""));
16
+ if (!Number.isFinite(startedMs) || startedMs <= 0) return false;
17
+ return nowMs - startedMs >= Math.max(0, Number(slowThresholdMs) || 0);
18
+ }
@@ -0,0 +1,44 @@
1
+ export function choosePreferredPriorityUsableEmbeddingModel(candidates = [], existingIndex = null) {
2
+ if (existingIndex?.complete === true) return null;
3
+ const list = Array.isArray(candidates) ? candidates.filter(Boolean) : [];
4
+ const firstSemanticPreferred = list.find((candidate) => String(candidate || "").trim() === "openai/text-embedding-3-small");
5
+ return firstSemanticPreferred || list[0] || null;
6
+ }
7
+
8
+ export function chooseDeferredResumeEmbeddingModel({
9
+ candidates = [],
10
+ failedModel = "",
11
+ cachedHealthModel = "",
12
+ penalizedModels = [],
13
+ }) {
14
+ const list = Array.isArray(candidates) ? candidates.filter(Boolean) : [];
15
+ if (list.length === 0) return "";
16
+ const failed = String(failedModel || "").trim();
17
+ const cached = String(cachedHealthModel || "").trim();
18
+ const penalized = new Set((Array.isArray(penalizedModels) ? penalizedModels : []).filter(Boolean));
19
+
20
+ const nonFailed = list.filter((candidate) => candidate !== failed);
21
+ const nonPenalizedNonFailed = nonFailed.filter((candidate) => !penalized.has(candidate));
22
+ if (cached && nonPenalizedNonFailed.includes(cached)) return cached;
23
+ if (nonPenalizedNonFailed.length > 0) return nonPenalizedNonFailed[0];
24
+
25
+ const healthyNonFailed = nonFailed;
26
+ if (cached && healthyNonFailed.includes(cached)) return cached;
27
+ if (healthyNonFailed.length > 0) return healthyNonFailed[0];
28
+
29
+ if (cached && list.includes(cached)) return cached;
30
+ return list[0] || "";
31
+ }
32
+
33
+ export function shouldUseResumeFallbackForCoarseDeferred({
34
+ force = false,
35
+ existingIndex = null,
36
+ hasReusableFineVectors = false,
37
+ resumeFallbackModel = "",
38
+ }) {
39
+ if (force) return false;
40
+ if (existingIndex?.complete === true) return false;
41
+ if (!resumeFallbackModel) return false;
42
+ if (hasReusableFineVectors) return true;
43
+ return existingIndex?.complete === false;
44
+ }
@@ -0,0 +1,18 @@
1
+ export function nextProviderSwitchSeconds({
2
+ currentAttempt = 0,
3
+ totalAttempts = 0,
4
+ timeoutMs = 0,
5
+ batchStartedAt = "",
6
+ updatedAt = "",
7
+ nowMs = Date.now(),
8
+ }) {
9
+ const current = Math.max(0, Number(currentAttempt || 0));
10
+ const total = Math.max(0, Number(totalAttempts || 0));
11
+ if (current <= 0 || total <= 1 || current >= total) return 0;
12
+ const startedMs = Date.parse(String(batchStartedAt || updatedAt || ""));
13
+ if (!Number.isFinite(startedMs) || startedMs <= 0) return 0;
14
+ const budgetMs = Math.max(0, Number(timeoutMs || 0));
15
+ if (!budgetMs) return 0;
16
+ const remainingMs = budgetMs - (Number(nowMs || 0) - startedMs);
17
+ return Math.max(0, Math.ceil(remainingMs / 1000));
18
+ }
@@ -0,0 +1,25 @@
1
+ export function describeEmbeddingRequestSource(source = "") {
2
+ const sourceText = String(source || "");
3
+ if (sourceText.startsWith("priority_usable_strategy_fast_path")) {
4
+ return "first-semantic fast path";
5
+ }
6
+ if (sourceText.startsWith("priority_usable_strategy_selection_timeout_fallback")) {
7
+ return "selection-timeout fallback";
8
+ }
9
+ if (sourceText.startsWith("priority_usable_strategy_fallback")) {
10
+ return "fallback";
11
+ }
12
+ if (sourceText.startsWith("priority_usable_strategy")) {
13
+ return "priority usable";
14
+ }
15
+ if (sourceText.startsWith("previous_failure_fallback_deferred_resume")) {
16
+ return "deferred resume fallback";
17
+ }
18
+ if (sourceText.startsWith("background_fine_post_priority_strategy")) {
19
+ return "post-priority background";
20
+ }
21
+ if (sourceText.startsWith("background_fine_strategy")) {
22
+ return "background fine";
23
+ }
24
+ return "";
25
+ }
@@ -0,0 +1,22 @@
1
+ export function resolveEmbeddingAttemptState({
2
+ defaultModel = "",
3
+ defaultTimeoutMs = 0,
4
+ defaultMaxRetries = 0,
5
+ attemptPlan = [],
6
+ attemptIndex = -1,
7
+ }) {
8
+ const attempts = Array.isArray(attemptPlan) ? attemptPlan : [];
9
+ if (attemptIndex >= 0 && attemptIndex < attempts.length) {
10
+ const attempt = attempts[attemptIndex] || {};
11
+ return {
12
+ model: String(attempt.model || defaultModel || ""),
13
+ timeoutMs: Number(attempt.timeoutMs || defaultTimeoutMs || 0),
14
+ maxRetries: Number(attempt.maxRetries ?? defaultMaxRetries ?? 0),
15
+ };
16
+ }
17
+ return {
18
+ model: String(defaultModel || ""),
19
+ timeoutMs: Number(defaultTimeoutMs || 0),
20
+ maxRetries: Number(defaultMaxRetries || 0),
21
+ };
22
+ }
@@ -0,0 +1,23 @@
1
+ export function shouldPreferPriorityUsableOverCachedHealth({
2
+ force = false,
3
+ hasReusableFineVectors = false,
4
+ priorityUsableModel = "",
5
+ cachedHealthModel = "",
6
+ cachedHealthOk = true,
7
+ cachedHealthLatencyMs = 0,
8
+ slowThresholdMs = 0,
9
+ }) {
10
+ if (force) return false;
11
+ if (hasReusableFineVectors) return false;
12
+ const preferred = String(priorityUsableModel || "").trim();
13
+ if (!preferred) return false;
14
+ const cached = String(cachedHealthModel || "").trim();
15
+ if (!cached) return true;
16
+ const healthyCached = cachedHealthOk !== false;
17
+ const latencyMs = Math.max(0, Number(cachedHealthLatencyMs) || 0);
18
+ const thresholdMs = Math.max(0, Number(slowThresholdMs) || 0);
19
+ if (healthyCached && cached !== preferred && thresholdMs > 0 && latencyMs > 0 && latencyMs <= thresholdMs) {
20
+ return false;
21
+ }
22
+ return cached !== preferred;
23
+ }
@@ -0,0 +1,14 @@
1
+ export function buildFineRunQueue({
2
+ priorityReadyFiles,
3
+ remainingFineFiles,
4
+ }) {
5
+ const queue = [];
6
+ const seen = new Set();
7
+ for (const file of [...(Array.isArray(priorityReadyFiles) ? priorityReadyFiles : []), ...(Array.isArray(remainingFineFiles) ? remainingFineFiles : [])]) {
8
+ const relativePath = file?.relativePath;
9
+ if (!relativePath || seen.has(relativePath)) continue;
10
+ seen.add(relativePath);
11
+ queue.push(file);
12
+ }
13
+ return queue;
14
+ }