@autorag/librarian 2.13.2 → 2.13.3

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/index.js CHANGED
@@ -2381,6 +2381,51 @@ var init_credential = __esm(() => {
2381
2381
  init_models();
2382
2382
  });
2383
2383
 
2384
+ // src/cloud/context-overflow.ts
2385
+ import {
2386
+ createAssistantMessageEventStream,
2387
+ isContextOverflow
2388
+ } from "@earendil-works/pi-ai";
2389
+ import { getApiProvider } from "@earendil-works/pi-ai/compat";
2390
+ function recordRequestEstimate(model, estimatedTokens) {
2391
+ lastEstimates.set(modelKey(model), estimatedTokens);
2392
+ }
2393
+ function noteContextOverflow(model) {
2394
+ const key = modelKey(model);
2395
+ const failed = lastEstimates.get(key);
2396
+ if (failed === undefined)
2397
+ return;
2398
+ ceilings.set(key, Math.min(Math.floor(failed / 2), ceilings.get(key) ?? Number.POSITIVE_INFINITY));
2399
+ }
2400
+ function contextOverflowCeiling(model) {
2401
+ return ceilings.get(modelKey(model));
2402
+ }
2403
+ function streamDazziSimple(model, context, options) {
2404
+ const api = getApiProvider(model.api);
2405
+ if (api === undefined)
2406
+ throw new Error(`No API provider registered for api: ${model.api}`);
2407
+ const inner = api.streamSimple(model, context, options);
2408
+ const stream = createAssistantMessageEventStream();
2409
+ (async () => {
2410
+ try {
2411
+ for await (const event of inner) {
2412
+ if (event.type === "error" && event.error.stopReason === "error" && isContextOverflow(event.error)) {
2413
+ noteContextOverflow(model);
2414
+ }
2415
+ stream.push(event);
2416
+ }
2417
+ } finally {
2418
+ stream.end();
2419
+ }
2420
+ })();
2421
+ return stream;
2422
+ }
2423
+ var lastEstimates, ceilings, modelKey = (model) => `${model.provider}/${model.id}`;
2424
+ var init_context_overflow = __esm(() => {
2425
+ lastEstimates = new Map;
2426
+ ceilings = new Map;
2427
+ });
2428
+
2384
2429
  // src/cloud/authorize.ts
2385
2430
  function buildAuthorizeUrl(params) {
2386
2431
  const url = new URL(`${normalizeBaseUrl(params.baseUrl)}${AUTHORIZE_PATH}`);
@@ -2736,6 +2781,7 @@ function createDazziProviderConfig(env = process.env) {
2736
2781
  name: PROVIDER_NAME,
2737
2782
  baseUrl: endpoints.apiBaseUrl,
2738
2783
  api: "openai-responses",
2784
+ streamSimple: streamDazziSimple,
2739
2785
  oauth: {
2740
2786
  name: PROVIDER_NAME,
2741
2787
  login: (callbacks) => loginDazzi(callbacks, { baseUrl }),
@@ -2751,6 +2797,7 @@ async function registerDazziProvider(runtime, env = process.env) {
2751
2797
  }
2752
2798
  var init_provider = __esm(() => {
2753
2799
  init_config2();
2800
+ init_context_overflow();
2754
2801
  init_models();
2755
2802
  init_oauth_login();
2756
2803
  });
@@ -28880,12 +28927,20 @@ function withBoundedOutput(model) {
28880
28927
  return { ...model, maxTokens: MAX_OUTPUT_TOKENS };
28881
28928
  }
28882
28929
  function guardAgentContextMessages(model, messages, useReportedUsage = true, fixedOverheadTokens = 0) {
28930
+ const guarded = guardWithinBudget(model, messages, useReportedUsage, fixedOverheadTokens);
28931
+ if (model !== undefined && guarded.length > 0) {
28932
+ recordRequestEstimate(model, estimateContextMessageTokens(guarded, false) + fixedOverheadTokens);
28933
+ }
28934
+ return guarded;
28935
+ }
28936
+ function guardWithinBudget(model, messages, useReportedUsage = true, fixedOverheadTokens = 0) {
28883
28937
  if (model === undefined || !Number.isFinite(model.contextWindow) || model.contextWindow <= 0 || messages.length === 0) {
28884
28938
  return messages;
28885
28939
  }
28886
28940
  const usableContext = Math.floor(model.contextWindow / CONTEXT_HEADROOM);
28887
28941
  const outputReserve = Math.min(Math.floor(usableContext / 4), MAX_OUTPUT_TOKENS, Number.isFinite(model.maxTokens) ? Math.max(0, model.maxTokens) : 0);
28888
- const inputBudget = Math.max(0, usableContext - outputReserve);
28942
+ const overflowCeiling = contextOverflowCeiling(model);
28943
+ const inputBudget = Math.min(Math.max(0, usableContext - outputReserve), overflowCeiling ?? Number.POSITIVE_INFINITY);
28889
28944
  const budget = Math.max(0, inputBudget - fixedOverheadTokens);
28890
28945
  const reported = useReportedUsage && findLastAssistantUsage(messages) !== undefined;
28891
28946
  if (estimateContextMessageTokens(messages, useReportedUsage) <= (reported ? inputBudget : budget)) {
@@ -29198,6 +29253,7 @@ function splitCandidates(text, sectionStart, sectionEnd, pattern = /^\[e?\d+\] [
29198
29253
  }
29199
29254
  var CONTEXT_HEADROOM = 1.2, MAX_OUTPUT_TOKENS = 32000, MIN_QUERY_TOKENS = 2000, GUARD_MARKER = "[AutoRAG context guard: omitted context to stay within the model context budget.]", RETRIEVAL_TOOL_PREFIX = "search_datasource_", RETRIEVAL_TOOL_NAMES;
29200
29255
  var init_context_token_guard = __esm(() => {
29256
+ init_context_overflow();
29201
29257
  RETRIEVAL_TOOL_NAMES = {
29202
29258
  jikji_find: true,
29203
29259
  search_all_documents: true,
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Context-overflow recovery for the hosted Dazzi Models API.
3
+ *
4
+ * The hosted server reports a request that exceeds the model's window as
5
+ * `400 context_length_exceeded` (or HTTP 413 for an oversized body), which Pi
6
+ * already recognises: it compacts, then retries once.
7
+ *
8
+ * That recovery is not enough on its own. Pi compacts by summarising older
9
+ * turns and keeping the latest ones whole, so an oversized tool result that is
10
+ * the newest turn survives compaction and the retry is rejected again. This
11
+ * module remembers which model just overflowed and how big the rejected request
12
+ * was, so the context guard can hold the retry to a fraction of that size.
13
+ */
14
+ import { type Api, type AssistantMessageEventStream, type Model, type SimpleStreamOptions, type TranscriptContext } from "@earendil-works/pi-ai";
15
+ /** The context guard reports the estimated size (its chars/4 unit, system prompt and tools included) of each request it releases. */
16
+ export declare function recordRequestEstimate(model: Pick<Model<Api>, "provider" | "id">, estimatedTokens: number): void;
17
+ /**
18
+ * Remember that `model` just overflowed, so later requests are held to half the
19
+ * estimated size of the one that failed. The ceiling only ever ratchets down,
20
+ * and is not set for a model whose requests the guard never sized.
21
+ */
22
+ export declare function noteContextOverflow(model: Pick<Model<Api>, "provider" | "id">): void;
23
+ /** The most estimated tokens a request to `model` may carry after an overflow, if it has overflowed. */
24
+ export declare function contextOverflowCeiling(model: Pick<Model<Api>, "provider" | "id">): number | undefined;
25
+ /**
26
+ * Pi's built-in `openai-responses` stream, unchanged except that a context
27
+ * overflow it reports is noted for {@link contextOverflowCeiling}.
28
+ */
29
+ export declare function streamDazziSimple(model: Model<Api>, context: TranscriptContext, options?: SimpleStreamOptions): AssistantMessageEventStream;
package/dist/core.js CHANGED
@@ -15098,6 +15098,51 @@ var init_permission_gate = __esm(() => {
15098
15098
  };
15099
15099
  });
15100
15100
 
15101
+ // src/cloud/context-overflow.ts
15102
+ import {
15103
+ createAssistantMessageEventStream,
15104
+ isContextOverflow
15105
+ } from "@earendil-works/pi-ai";
15106
+ import { getApiProvider } from "@earendil-works/pi-ai/compat";
15107
+ function recordRequestEstimate(model, estimatedTokens) {
15108
+ lastEstimates.set(modelKey(model), estimatedTokens);
15109
+ }
15110
+ function noteContextOverflow(model) {
15111
+ const key = modelKey(model);
15112
+ const failed = lastEstimates.get(key);
15113
+ if (failed === undefined)
15114
+ return;
15115
+ ceilings.set(key, Math.min(Math.floor(failed / 2), ceilings.get(key) ?? Number.POSITIVE_INFINITY));
15116
+ }
15117
+ function contextOverflowCeiling(model) {
15118
+ return ceilings.get(modelKey(model));
15119
+ }
15120
+ function streamDazziSimple(model, context, options) {
15121
+ const api = getApiProvider(model.api);
15122
+ if (api === undefined)
15123
+ throw new Error(`No API provider registered for api: ${model.api}`);
15124
+ const inner = api.streamSimple(model, context, options);
15125
+ const stream = createAssistantMessageEventStream();
15126
+ (async () => {
15127
+ try {
15128
+ for await (const event of inner) {
15129
+ if (event.type === "error" && event.error.stopReason === "error" && isContextOverflow(event.error)) {
15130
+ noteContextOverflow(model);
15131
+ }
15132
+ stream.push(event);
15133
+ }
15134
+ } finally {
15135
+ stream.end();
15136
+ }
15137
+ })();
15138
+ return stream;
15139
+ }
15140
+ var lastEstimates, ceilings, modelKey = (model) => `${model.provider}/${model.id}`;
15141
+ var init_context_overflow = __esm(() => {
15142
+ lastEstimates = new Map;
15143
+ ceilings = new Map;
15144
+ });
15145
+
15101
15146
  // src/cloud/authorize.ts
15102
15147
  function buildAuthorizeUrl(params) {
15103
15148
  const url = new URL(`${normalizeBaseUrl(params.baseUrl)}${AUTHORIZE_PATH}`);
@@ -15453,6 +15498,7 @@ function createDazziProviderConfig(env = process.env) {
15453
15498
  name: PROVIDER_NAME,
15454
15499
  baseUrl: endpoints.apiBaseUrl,
15455
15500
  api: "openai-responses",
15501
+ streamSimple: streamDazziSimple,
15456
15502
  oauth: {
15457
15503
  name: PROVIDER_NAME,
15458
15504
  login: (callbacks) => loginDazzi(callbacks, { baseUrl }),
@@ -15468,6 +15514,7 @@ async function registerDazziProvider(runtime, env = process.env) {
15468
15514
  }
15469
15515
  var init_provider2 = __esm(() => {
15470
15516
  init_config();
15517
+ init_context_overflow();
15471
15518
  init_models();
15472
15519
  init_oauth_login();
15473
15520
  });
@@ -26850,12 +26897,20 @@ function withBoundedOutput(model) {
26850
26897
  return { ...model, maxTokens: MAX_OUTPUT_TOKENS };
26851
26898
  }
26852
26899
  function guardAgentContextMessages(model, messages, useReportedUsage = true, fixedOverheadTokens = 0) {
26900
+ const guarded = guardWithinBudget(model, messages, useReportedUsage, fixedOverheadTokens);
26901
+ if (model !== undefined && guarded.length > 0) {
26902
+ recordRequestEstimate(model, estimateContextMessageTokens(guarded, false) + fixedOverheadTokens);
26903
+ }
26904
+ return guarded;
26905
+ }
26906
+ function guardWithinBudget(model, messages, useReportedUsage = true, fixedOverheadTokens = 0) {
26853
26907
  if (model === undefined || !Number.isFinite(model.contextWindow) || model.contextWindow <= 0 || messages.length === 0) {
26854
26908
  return messages;
26855
26909
  }
26856
26910
  const usableContext = Math.floor(model.contextWindow / CONTEXT_HEADROOM);
26857
26911
  const outputReserve = Math.min(Math.floor(usableContext / 4), MAX_OUTPUT_TOKENS, Number.isFinite(model.maxTokens) ? Math.max(0, model.maxTokens) : 0);
26858
- const inputBudget = Math.max(0, usableContext - outputReserve);
26912
+ const overflowCeiling = contextOverflowCeiling(model);
26913
+ const inputBudget = Math.min(Math.max(0, usableContext - outputReserve), overflowCeiling ?? Number.POSITIVE_INFINITY);
26859
26914
  const budget = Math.max(0, inputBudget - fixedOverheadTokens);
26860
26915
  const reported = useReportedUsage && findLastAssistantUsage(messages) !== undefined;
26861
26916
  if (estimateContextMessageTokens(messages, useReportedUsage) <= (reported ? inputBudget : budget)) {
@@ -27168,6 +27223,7 @@ function splitCandidates(text, sectionStart, sectionEnd, pattern = /^\[e?\d+\] [
27168
27223
  }
27169
27224
  var CONTEXT_HEADROOM = 1.2, MAX_OUTPUT_TOKENS = 32000, MIN_QUERY_TOKENS = 2000, GUARD_MARKER = "[AutoRAG context guard: omitted context to stay within the model context budget.]", RETRIEVAL_TOOL_PREFIX = "search_datasource_", RETRIEVAL_TOOL_NAMES;
27170
27225
  var init_context_token_guard = __esm(() => {
27226
+ init_context_overflow();
27171
27227
  RETRIEVAL_TOOL_NAMES = {
27172
27228
  jikji_find: true,
27173
27229
  search_all_documents: true,
package/dist/index.js CHANGED
@@ -15098,6 +15098,51 @@ var init_permission_gate = __esm(() => {
15098
15098
  };
15099
15099
  });
15100
15100
 
15101
+ // src/cloud/context-overflow.ts
15102
+ import {
15103
+ createAssistantMessageEventStream,
15104
+ isContextOverflow
15105
+ } from "@earendil-works/pi-ai";
15106
+ import { getApiProvider } from "@earendil-works/pi-ai/compat";
15107
+ function recordRequestEstimate(model, estimatedTokens) {
15108
+ lastEstimates.set(modelKey(model), estimatedTokens);
15109
+ }
15110
+ function noteContextOverflow(model) {
15111
+ const key = modelKey(model);
15112
+ const failed = lastEstimates.get(key);
15113
+ if (failed === undefined)
15114
+ return;
15115
+ ceilings.set(key, Math.min(Math.floor(failed / 2), ceilings.get(key) ?? Number.POSITIVE_INFINITY));
15116
+ }
15117
+ function contextOverflowCeiling(model) {
15118
+ return ceilings.get(modelKey(model));
15119
+ }
15120
+ function streamDazziSimple(model, context, options) {
15121
+ const api = getApiProvider(model.api);
15122
+ if (api === undefined)
15123
+ throw new Error(`No API provider registered for api: ${model.api}`);
15124
+ const inner = api.streamSimple(model, context, options);
15125
+ const stream = createAssistantMessageEventStream();
15126
+ (async () => {
15127
+ try {
15128
+ for await (const event of inner) {
15129
+ if (event.type === "error" && event.error.stopReason === "error" && isContextOverflow(event.error)) {
15130
+ noteContextOverflow(model);
15131
+ }
15132
+ stream.push(event);
15133
+ }
15134
+ } finally {
15135
+ stream.end();
15136
+ }
15137
+ })();
15138
+ return stream;
15139
+ }
15140
+ var lastEstimates, ceilings, modelKey = (model) => `${model.provider}/${model.id}`;
15141
+ var init_context_overflow = __esm(() => {
15142
+ lastEstimates = new Map;
15143
+ ceilings = new Map;
15144
+ });
15145
+
15101
15146
  // src/cloud/authorize.ts
15102
15147
  function buildAuthorizeUrl(params) {
15103
15148
  const url = new URL(`${normalizeBaseUrl(params.baseUrl)}${AUTHORIZE_PATH}`);
@@ -15453,6 +15498,7 @@ function createDazziProviderConfig(env = process.env) {
15453
15498
  name: PROVIDER_NAME,
15454
15499
  baseUrl: endpoints.apiBaseUrl,
15455
15500
  api: "openai-responses",
15501
+ streamSimple: streamDazziSimple,
15456
15502
  oauth: {
15457
15503
  name: PROVIDER_NAME,
15458
15504
  login: (callbacks) => loginDazzi(callbacks, { baseUrl }),
@@ -15468,6 +15514,7 @@ async function registerDazziProvider(runtime, env = process.env) {
15468
15514
  }
15469
15515
  var init_provider2 = __esm(() => {
15470
15516
  init_config();
15517
+ init_context_overflow();
15471
15518
  init_models();
15472
15519
  init_oauth_login();
15473
15520
  });
@@ -26850,12 +26897,20 @@ function withBoundedOutput(model) {
26850
26897
  return { ...model, maxTokens: MAX_OUTPUT_TOKENS };
26851
26898
  }
26852
26899
  function guardAgentContextMessages(model, messages, useReportedUsage = true, fixedOverheadTokens = 0) {
26900
+ const guarded = guardWithinBudget(model, messages, useReportedUsage, fixedOverheadTokens);
26901
+ if (model !== undefined && guarded.length > 0) {
26902
+ recordRequestEstimate(model, estimateContextMessageTokens(guarded, false) + fixedOverheadTokens);
26903
+ }
26904
+ return guarded;
26905
+ }
26906
+ function guardWithinBudget(model, messages, useReportedUsage = true, fixedOverheadTokens = 0) {
26853
26907
  if (model === undefined || !Number.isFinite(model.contextWindow) || model.contextWindow <= 0 || messages.length === 0) {
26854
26908
  return messages;
26855
26909
  }
26856
26910
  const usableContext = Math.floor(model.contextWindow / CONTEXT_HEADROOM);
26857
26911
  const outputReserve = Math.min(Math.floor(usableContext / 4), MAX_OUTPUT_TOKENS, Number.isFinite(model.maxTokens) ? Math.max(0, model.maxTokens) : 0);
26858
- const inputBudget = Math.max(0, usableContext - outputReserve);
26912
+ const overflowCeiling = contextOverflowCeiling(model);
26913
+ const inputBudget = Math.min(Math.max(0, usableContext - outputReserve), overflowCeiling ?? Number.POSITIVE_INFINITY);
26859
26914
  const budget = Math.max(0, inputBudget - fixedOverheadTokens);
26860
26915
  const reported = useReportedUsage && findLastAssistantUsage(messages) !== undefined;
26861
26916
  if (estimateContextMessageTokens(messages, useReportedUsage) <= (reported ? inputBudget : budget)) {
@@ -27168,6 +27223,7 @@ function splitCandidates(text, sectionStart, sectionEnd, pattern = /^\[e?\d+\] [
27168
27223
  }
27169
27224
  var CONTEXT_HEADROOM = 1.2, MAX_OUTPUT_TOKENS = 32000, MIN_QUERY_TOKENS = 2000, GUARD_MARKER = "[AutoRAG context guard: omitted context to stay within the model context budget.]", RETRIEVAL_TOOL_PREFIX = "search_datasource_", RETRIEVAL_TOOL_NAMES;
27170
27225
  var init_context_token_guard = __esm(() => {
27226
+ init_context_overflow();
27171
27227
  RETRIEVAL_TOOL_NAMES = {
27172
27228
  jikji_find: true,
27173
27229
  search_all_documents: true,
package/dist/mcp/index.js CHANGED
@@ -15099,6 +15099,51 @@ var init_permission_gate = __esm(() => {
15099
15099
  };
15100
15100
  });
15101
15101
 
15102
+ // src/cloud/context-overflow.ts
15103
+ import {
15104
+ createAssistantMessageEventStream,
15105
+ isContextOverflow
15106
+ } from "@earendil-works/pi-ai";
15107
+ import { getApiProvider } from "@earendil-works/pi-ai/compat";
15108
+ function recordRequestEstimate(model, estimatedTokens) {
15109
+ lastEstimates.set(modelKey(model), estimatedTokens);
15110
+ }
15111
+ function noteContextOverflow(model) {
15112
+ const key = modelKey(model);
15113
+ const failed = lastEstimates.get(key);
15114
+ if (failed === undefined)
15115
+ return;
15116
+ ceilings.set(key, Math.min(Math.floor(failed / 2), ceilings.get(key) ?? Number.POSITIVE_INFINITY));
15117
+ }
15118
+ function contextOverflowCeiling(model) {
15119
+ return ceilings.get(modelKey(model));
15120
+ }
15121
+ function streamDazziSimple(model, context, options) {
15122
+ const api = getApiProvider(model.api);
15123
+ if (api === undefined)
15124
+ throw new Error(`No API provider registered for api: ${model.api}`);
15125
+ const inner = api.streamSimple(model, context, options);
15126
+ const stream = createAssistantMessageEventStream();
15127
+ (async () => {
15128
+ try {
15129
+ for await (const event of inner) {
15130
+ if (event.type === "error" && event.error.stopReason === "error" && isContextOverflow(event.error)) {
15131
+ noteContextOverflow(model);
15132
+ }
15133
+ stream.push(event);
15134
+ }
15135
+ } finally {
15136
+ stream.end();
15137
+ }
15138
+ })();
15139
+ return stream;
15140
+ }
15141
+ var lastEstimates, ceilings, modelKey = (model) => `${model.provider}/${model.id}`;
15142
+ var init_context_overflow = __esm(() => {
15143
+ lastEstimates = new Map;
15144
+ ceilings = new Map;
15145
+ });
15146
+
15102
15147
  // src/cloud/authorize.ts
15103
15148
  function buildAuthorizeUrl(params) {
15104
15149
  const url = new URL(`${normalizeBaseUrl(params.baseUrl)}${AUTHORIZE_PATH}`);
@@ -15454,6 +15499,7 @@ function createDazziProviderConfig(env = process.env) {
15454
15499
  name: PROVIDER_NAME,
15455
15500
  baseUrl: endpoints.apiBaseUrl,
15456
15501
  api: "openai-responses",
15502
+ streamSimple: streamDazziSimple,
15457
15503
  oauth: {
15458
15504
  name: PROVIDER_NAME,
15459
15505
  login: (callbacks) => loginDazzi(callbacks, { baseUrl }),
@@ -15469,6 +15515,7 @@ async function registerDazziProvider(runtime, env = process.env) {
15469
15515
  }
15470
15516
  var init_provider2 = __esm(() => {
15471
15517
  init_config();
15518
+ init_context_overflow();
15472
15519
  init_models();
15473
15520
  init_oauth_login();
15474
15521
  });
@@ -26851,12 +26898,20 @@ function withBoundedOutput(model) {
26851
26898
  return { ...model, maxTokens: MAX_OUTPUT_TOKENS };
26852
26899
  }
26853
26900
  function guardAgentContextMessages(model, messages, useReportedUsage = true, fixedOverheadTokens = 0) {
26901
+ const guarded = guardWithinBudget(model, messages, useReportedUsage, fixedOverheadTokens);
26902
+ if (model !== undefined && guarded.length > 0) {
26903
+ recordRequestEstimate(model, estimateContextMessageTokens(guarded, false) + fixedOverheadTokens);
26904
+ }
26905
+ return guarded;
26906
+ }
26907
+ function guardWithinBudget(model, messages, useReportedUsage = true, fixedOverheadTokens = 0) {
26854
26908
  if (model === undefined || !Number.isFinite(model.contextWindow) || model.contextWindow <= 0 || messages.length === 0) {
26855
26909
  return messages;
26856
26910
  }
26857
26911
  const usableContext = Math.floor(model.contextWindow / CONTEXT_HEADROOM);
26858
26912
  const outputReserve = Math.min(Math.floor(usableContext / 4), MAX_OUTPUT_TOKENS, Number.isFinite(model.maxTokens) ? Math.max(0, model.maxTokens) : 0);
26859
- const inputBudget = Math.max(0, usableContext - outputReserve);
26913
+ const overflowCeiling = contextOverflowCeiling(model);
26914
+ const inputBudget = Math.min(Math.max(0, usableContext - outputReserve), overflowCeiling ?? Number.POSITIVE_INFINITY);
26860
26915
  const budget = Math.max(0, inputBudget - fixedOverheadTokens);
26861
26916
  const reported = useReportedUsage && findLastAssistantUsage(messages) !== undefined;
26862
26917
  if (estimateContextMessageTokens(messages, useReportedUsage) <= (reported ? inputBudget : budget)) {
@@ -27169,6 +27224,7 @@ function splitCandidates(text, sectionStart, sectionEnd, pattern = /^\[e?\d+\] [
27169
27224
  }
27170
27225
  var CONTEXT_HEADROOM = 1.2, MAX_OUTPUT_TOKENS = 32000, MIN_QUERY_TOKENS = 2000, GUARD_MARKER = "[AutoRAG context guard: omitted context to stay within the model context budget.]", RETRIEVAL_TOOL_PREFIX = "search_datasource_", RETRIEVAL_TOOL_NAMES;
27171
27226
  var init_context_token_guard = __esm(() => {
27227
+ init_context_overflow();
27172
27228
  RETRIEVAL_TOOL_NAMES = {
27173
27229
  jikji_find: true,
27174
27230
  search_all_documents: true,
package/dist/profiles.js CHANGED
@@ -968,6 +968,51 @@ var init_credential = __esm(() => {
968
968
  init_models();
969
969
  });
970
970
 
971
+ // src/cloud/context-overflow.ts
972
+ import {
973
+ createAssistantMessageEventStream,
974
+ isContextOverflow
975
+ } from "@earendil-works/pi-ai";
976
+ import { getApiProvider } from "@earendil-works/pi-ai/compat";
977
+ function recordRequestEstimate(model, estimatedTokens) {
978
+ lastEstimates.set(modelKey(model), estimatedTokens);
979
+ }
980
+ function noteContextOverflow(model) {
981
+ const key = modelKey(model);
982
+ const failed = lastEstimates.get(key);
983
+ if (failed === undefined)
984
+ return;
985
+ ceilings.set(key, Math.min(Math.floor(failed / 2), ceilings.get(key) ?? Number.POSITIVE_INFINITY));
986
+ }
987
+ function contextOverflowCeiling(model) {
988
+ return ceilings.get(modelKey(model));
989
+ }
990
+ function streamDazziSimple(model, context, options) {
991
+ const api = getApiProvider(model.api);
992
+ if (api === undefined)
993
+ throw new Error(`No API provider registered for api: ${model.api}`);
994
+ const inner = api.streamSimple(model, context, options);
995
+ const stream = createAssistantMessageEventStream();
996
+ (async () => {
997
+ try {
998
+ for await (const event of inner) {
999
+ if (event.type === "error" && event.error.stopReason === "error" && isContextOverflow(event.error)) {
1000
+ noteContextOverflow(model);
1001
+ }
1002
+ stream.push(event);
1003
+ }
1004
+ } finally {
1005
+ stream.end();
1006
+ }
1007
+ })();
1008
+ return stream;
1009
+ }
1010
+ var lastEstimates, ceilings, modelKey = (model) => `${model.provider}/${model.id}`;
1011
+ var init_context_overflow = __esm(() => {
1012
+ lastEstimates = new Map;
1013
+ ceilings = new Map;
1014
+ });
1015
+
971
1016
  // src/cloud/authorize.ts
972
1017
  function buildAuthorizeUrl(params) {
973
1018
  const url = new URL(`${normalizeBaseUrl(params.baseUrl)}${AUTHORIZE_PATH}`);
@@ -1323,6 +1368,7 @@ function createDazziProviderConfig(env = process.env) {
1323
1368
  name: PROVIDER_NAME,
1324
1369
  baseUrl: endpoints.apiBaseUrl,
1325
1370
  api: "openai-responses",
1371
+ streamSimple: streamDazziSimple,
1326
1372
  oauth: {
1327
1373
  name: PROVIDER_NAME,
1328
1374
  login: (callbacks) => loginDazzi(callbacks, { baseUrl }),
@@ -1338,6 +1384,7 @@ async function registerDazziProvider(runtime, env = process.env) {
1338
1384
  }
1339
1385
  var init_provider = __esm(() => {
1340
1386
  init_config();
1387
+ init_context_overflow();
1341
1388
  init_models();
1342
1389
  init_oauth_login();
1343
1390
  });
@@ -29245,12 +29292,20 @@ function withBoundedOutput(model) {
29245
29292
  return { ...model, maxTokens: MAX_OUTPUT_TOKENS };
29246
29293
  }
29247
29294
  function guardAgentContextMessages(model, messages, useReportedUsage = true, fixedOverheadTokens = 0) {
29295
+ const guarded = guardWithinBudget(model, messages, useReportedUsage, fixedOverheadTokens);
29296
+ if (model !== undefined && guarded.length > 0) {
29297
+ recordRequestEstimate(model, estimateContextMessageTokens(guarded, false) + fixedOverheadTokens);
29298
+ }
29299
+ return guarded;
29300
+ }
29301
+ function guardWithinBudget(model, messages, useReportedUsage = true, fixedOverheadTokens = 0) {
29248
29302
  if (model === undefined || !Number.isFinite(model.contextWindow) || model.contextWindow <= 0 || messages.length === 0) {
29249
29303
  return messages;
29250
29304
  }
29251
29305
  const usableContext = Math.floor(model.contextWindow / CONTEXT_HEADROOM);
29252
29306
  const outputReserve = Math.min(Math.floor(usableContext / 4), MAX_OUTPUT_TOKENS, Number.isFinite(model.maxTokens) ? Math.max(0, model.maxTokens) : 0);
29253
- const inputBudget = Math.max(0, usableContext - outputReserve);
29307
+ const overflowCeiling = contextOverflowCeiling(model);
29308
+ const inputBudget = Math.min(Math.max(0, usableContext - outputReserve), overflowCeiling ?? Number.POSITIVE_INFINITY);
29254
29309
  const budget = Math.max(0, inputBudget - fixedOverheadTokens);
29255
29310
  const reported = useReportedUsage && findLastAssistantUsage(messages) !== undefined;
29256
29311
  if (estimateContextMessageTokens(messages, useReportedUsage) <= (reported ? inputBudget : budget)) {
@@ -29563,6 +29618,7 @@ function splitCandidates(text, sectionStart, sectionEnd, pattern = /^\[e?\d+\] [
29563
29618
  }
29564
29619
  var CONTEXT_HEADROOM = 1.2, MAX_OUTPUT_TOKENS = 32000, MIN_QUERY_TOKENS = 2000, GUARD_MARKER = "[AutoRAG context guard: omitted context to stay within the model context budget.]", RETRIEVAL_TOOL_PREFIX = "search_datasource_", RETRIEVAL_TOOL_NAMES;
29565
29620
  var init_context_token_guard = __esm(() => {
29621
+ init_context_overflow();
29566
29622
  RETRIEVAL_TOOL_NAMES = {
29567
29623
  jikji_find: true,
29568
29624
  search_all_documents: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autorag/librarian",
3
- "version": "2.13.2",
3
+ "version": "2.13.3",
4
4
  "description": "Personal librarian agent for office work on the Pi framework, with pluggable retrieval methods",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {