@dudko.dev/agent-web 0.0.20 → 0.0.22

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/index.js CHANGED
@@ -10,11 +10,43 @@ import {
10
10
  openAgentWebDB
11
11
  } from "./chunk-V7COB2EA.js";
12
12
  import {
13
+ AttachmentsNotSupportedError,
14
+ ContextWindowExceededError,
15
+ ImagesNotSupportedError,
16
+ TOOL_SEARCH_WINDOW_SHARE,
17
+ WEBLLM_DEFAULT_CONTEXT_WINDOW,
18
+ attachmentKind,
19
+ clip,
20
+ compactHistory,
21
+ compactSteps,
22
+ compressHistory,
23
+ contextOverflowOf,
24
+ contextWindowOf,
13
25
  createWebLLMModel,
26
+ estimateTokens,
27
+ fitCompactionToWindow,
28
+ generate,
29
+ generateStructured,
30
+ isAttachmentRefusal,
31
+ isImageRefusal,
14
32
  isWebGPUAvailable,
33
+ mediaTypeOf,
34
+ messageTokens,
35
+ modelLabel,
36
+ normalizeUsage,
15
37
  preloadWebLLMModel,
16
- unloadWebLLMModel
17
- } from "./chunk-IT65EW77.js";
38
+ promptOf,
39
+ resolveCompaction,
40
+ stream,
41
+ timeoutSignal,
42
+ toFilePart,
43
+ toImagePart,
44
+ toolDefinitionTokens,
45
+ unloadWebLLMModel,
46
+ unsupportedAttachment,
47
+ webLLMContextWindow,
48
+ withWebLLMContextWindow
49
+ } from "./chunk-YA6TQQ3Q.js";
18
50
 
19
51
  // src/caching.ts
20
52
  var resolveCaching = (s) => {
@@ -59,145 +91,6 @@ var withRollingBreakpoint = (messages, caching) => {
59
91
  return out;
60
92
  };
61
93
 
62
- // src/llm/generate.ts
63
- import {
64
- generateObject,
65
- generateText,
66
- streamText
67
- } from "ai";
68
-
69
- // src/llm/util.ts
70
- var clip = (s, max) => s.length > max ? `${s.slice(0, max - 1)}\u2026` : s;
71
- var promptOf = (opts) => opts.messages ? { messages: opts.messages } : { prompt: opts.prompt ?? "" };
72
- var normalizeUsage = (u) => {
73
- const inputTokens = u?.inputTokens ?? 0;
74
- const outputTokens = u?.outputTokens ?? 0;
75
- return {
76
- inputTokens,
77
- outputTokens,
78
- totalTokens: u?.totalTokens ?? inputTokens + outputTokens,
79
- reasoningTokens: u?.outputTokenDetails?.reasoningTokens ?? u?.reasoningTokens ?? 0,
80
- cachedInputTokens: u?.inputTokenDetails?.cacheReadTokens ?? u?.cachedInputTokens ?? 0,
81
- cacheWriteTokens: u?.inputTokenDetails?.cacheWriteTokens ?? 0
82
- };
83
- };
84
- var timeoutSignal = (signal, ms) => {
85
- if (!ms || ms <= 0) return signal;
86
- const timeout = AbortSignal.timeout(ms);
87
- if (!signal) return timeout;
88
- return typeof AbortSignal.any === "function" ? AbortSignal.any([signal, timeout]) : signal;
89
- };
90
-
91
- // src/llm/generate.ts
92
- var callSettings = (opts) => ({
93
- ...opts.system !== void 0 ? { instructions: opts.system } : {},
94
- maxOutputTokens: opts.maxOutputTokens,
95
- temperature: opts.temperature,
96
- ...opts.reasoning ? { reasoning: opts.reasoning } : {},
97
- ...opts.providerOptions ? { providerOptions: opts.providerOptions } : {},
98
- abortSignal: timeoutSignal(opts.abortSignal, opts.timeoutMs)
99
- });
100
- var generate = (model, opts = {}) => generateText({
101
- model,
102
- ...callSettings(opts),
103
- ...promptOf(opts),
104
- tools: opts.tools
105
- });
106
- var stream = (model, opts = {}) => streamText({
107
- model,
108
- ...callSettings(opts),
109
- ...promptOf(opts),
110
- tools: opts.tools
111
- });
112
- var generateStructured = (model, schema, opts = {}) => generateObject({
113
- model,
114
- schema,
115
- ...callSettings(opts),
116
- ...promptOf(opts)
117
- });
118
-
119
- // src/memory/compress.ts
120
- var resolveCompaction = (c) => {
121
- const contextWindowTokens = c?.contextWindowTokens ?? 128e3;
122
- return {
123
- auto: c?.auto ?? true,
124
- contextWindowTokens,
125
- thresholdTokens: c?.thresholdTokens ?? Math.floor(contextWindowTokens / 2),
126
- keepRecentTurns: c?.keepRecentTurns ?? 4,
127
- keepRecentSteps: c?.keepRecentSteps ?? 3,
128
- summaryMaxTokens: c?.summaryMaxTokens ?? 1024,
129
- maxToolOutputChars: c?.maxToolOutputChars ?? 2e4,
130
- clearToolResultsAfterTokens: c?.clearToolResultsAfterTokens ?? Math.floor(contextWindowTokens / 4),
131
- keepToolResults: c?.keepToolResults ?? 3
132
- };
133
- };
134
- var estimateTokens = (text) => Math.ceil((text ?? "").length / 4);
135
- var messageTokens = (msgs) => msgs.reduce((n, m) => n + estimateTokens(`${m.role}: ${m.content}
136
- `), 0);
137
- var SUMMARY_SYSTEM = "Summarize the following conversation into a compact set of durable facts, decisions, identifiers, open tasks and user preferences. Keep names, numbers and IDs verbatim. Output plain text only.";
138
- var compressHistory = async (messages, model, opts = {}) => {
139
- const keepRecent = opts.keepRecent ?? 6;
140
- if (messages.length <= keepRecent + 1) return messages;
141
- if (!opts.force) {
142
- if (opts.thresholdTokens !== void 0) {
143
- if (opts.thresholdTokens <= 0 || messageTokens(messages) <= opts.thresholdTokens) {
144
- return messages;
145
- }
146
- } else {
147
- const maxChars = opts.maxChars ?? 12e3;
148
- const chars = messages.reduce((n, m) => n + m.content.length, 0);
149
- if (maxChars <= 0 || chars <= maxChars) return messages;
150
- }
151
- }
152
- const head = messages.slice(0, messages.length - keepRecent);
153
- const tail = messages.slice(messages.length - keepRecent);
154
- const transcript = head.map((m) => `${m.role}: ${m.content}`).join("\n").slice(-48e3);
155
- try {
156
- const result = await generate(model, {
157
- system: SUMMARY_SYSTEM,
158
- prompt: transcript,
159
- maxOutputTokens: opts.summaryMaxTokens ?? 400,
160
- timeoutMs: opts.timeoutMs,
161
- abortSignal: opts.abortSignal
162
- });
163
- opts.onUsage?.(normalizeUsage(result.usage));
164
- const clean = (result.text || "").trim();
165
- if (!clean) return messages;
166
- const summaryMsg = {
167
- role: "system",
168
- content: `Summary of earlier conversation:
169
- ${clean}`,
170
- ts: head[0]?.ts
171
- };
172
- return [summaryMsg, ...tail];
173
- } catch {
174
- return messages;
175
- }
176
- };
177
- var compactHistory = compressHistory;
178
- var TRACE_SYSTEM = "Summarize these completed agent steps into a compact progress note: what was done, what was found (keep names, numbers and IDs verbatim) and what failed. Plain text only.";
179
- var compactSteps = async (done, model, opts) => {
180
- const keepRecent = opts.keepRecent ?? 3;
181
- if (done.length <= keepRecent + 1) return done;
182
- if (!opts.force && estimateTokens(done.join("\n")) <= opts.thresholdTokens) return done;
183
- const head = done.slice(0, done.length - keepRecent);
184
- try {
185
- const result = await generate(model, {
186
- system: TRACE_SYSTEM,
187
- prompt: head.map((d, i) => `${i + 1}. ${d}`).join("\n"),
188
- maxOutputTokens: opts.summaryMaxTokens ?? 600,
189
- timeoutMs: opts.timeoutMs,
190
- abortSignal: opts.abortSignal
191
- });
192
- opts.onUsage?.(normalizeUsage(result.usage));
193
- const clean = (result.text || "").trim();
194
- if (!clean) return done;
195
- return [`Summary of ${head.length} earlier step(s): ${clean}`, ...done.slice(head.length)];
196
- } catch {
197
- return done;
198
- }
199
- };
200
-
201
94
  // src/config.ts
202
95
  var resolveConfig = (c) => ({
203
96
  clientName: c.clientName ?? "agent-web",
@@ -361,7 +254,7 @@ var buildModelFromStage = async (resolved, credentials, clientName = "agent-web"
361
254
  const apiKey = await resolveApiKey(spec, credentials);
362
255
  switch (spec.providerType) {
363
256
  case "web-llm": {
364
- const { createWebLLMModel: createWebLLMModel2 } = await import("./webllm-XUBUNKFN.js");
257
+ const { createWebLLMModel: createWebLLMModel2 } = await import("./webllm-QTJ3EGTG.js");
365
258
  return createWebLLMModel2(spec.model, providerOptions);
366
259
  }
367
260
  case "gateway": {
@@ -1169,9 +1062,9 @@ var schemaHintOf = async (t) => {
1169
1062
 
1170
1063
  // src/llm/tool-loop.ts
1171
1064
  import {
1172
- generateText as generateText2,
1065
+ generateText,
1173
1066
  stepCountIs,
1174
- streamText as streamText2
1067
+ streamText
1175
1068
  } from "ai";
1176
1069
 
1177
1070
  // src/agent/loop-types.ts
@@ -1410,7 +1303,7 @@ var runNative = async (model, opts) => {
1410
1303
  const caching = opts.caching?.enabled ? opts.caching : void 0;
1411
1304
  const clear = opts.clearToolResults ? createToolResultClearer(opts.clearToolResults, opts.callbacks?.onToolResultsCleared) : void 0;
1412
1305
  const editMessages = caching || clear;
1413
- const result = streamText2({
1306
+ const result = streamText({
1414
1307
  model,
1415
1308
  tools: opts.tools,
1416
1309
  ...initialActive ? { activeTools: initialActive } : {},
@@ -1517,7 +1410,7 @@ var runPrompted = async (model, opts) => {
1517
1410
  break;
1518
1411
  }
1519
1412
  const before = new Set(Object.keys(callable()));
1520
- const result = await generateText2({
1413
+ const result = await generateText({
1521
1414
  model,
1522
1415
  ...callExtras(opts),
1523
1416
  messages: opts.caching ? withRollingBreakpoint(messages, opts.caching) : messages,
@@ -1566,7 +1459,8 @@ var resolveThinking = (setting) => {
1566
1459
  const cfg = normalize(setting);
1567
1460
  if (!cfg) return {};
1568
1461
  const level = cfg.level ?? "medium";
1569
- if (level === "none") return { reasoning: "none" };
1462
+ const webllm = (on) => ({ "web-llm": { extra_body: { enable_thinking: on } } });
1463
+ if (level === "none") return { reasoning: "none", providerOptions: webllm(false) };
1570
1464
  const includeThoughts = cfg.includeThoughts !== false;
1571
1465
  const budget = cfg.budgetTokens;
1572
1466
  if (typeof budget === "number" && budget > 0) {
@@ -1574,16 +1468,18 @@ var resolveThinking = (setting) => {
1574
1468
  reasoning: level,
1575
1469
  providerOptions: {
1576
1470
  anthropic: { thinking: { type: "enabled", budgetTokens: budget } },
1577
- google: { thinkingConfig: { thinkingBudget: budget, includeThoughts } }
1471
+ google: { thinkingConfig: { thinkingBudget: budget, includeThoughts } },
1472
+ ...webllm(true)
1578
1473
  }
1579
1474
  };
1580
1475
  }
1581
- if (!includeThoughts) return { reasoning: level };
1476
+ if (!includeThoughts) return { reasoning: level, providerOptions: webllm(true) };
1582
1477
  return {
1583
1478
  reasoning: level,
1584
1479
  providerOptions: {
1585
1480
  google: { thinkingConfig: { includeThoughts: true } },
1586
- openai: { reasoningSummary: "auto" }
1481
+ openai: { reasoningSummary: "auto" },
1482
+ ...webllm(true)
1587
1483
  }
1588
1484
  };
1589
1485
  };
@@ -1605,89 +1501,6 @@ var mergeProviderOptions = (...maps) => {
1605
1501
  return out;
1606
1502
  };
1607
1503
 
1608
- // src/images.ts
1609
- var DATA_URL_RE = /^data:([^;,]+)?;base64,(.*)$/s;
1610
- var HTTP_RE = /^https?:\/\//i;
1611
- var mediaTypeOf = (f) => {
1612
- if (f.mediaType) return f.mediaType;
1613
- if (typeof f.data === "string") {
1614
- const m = DATA_URL_RE.exec(f.data);
1615
- if (m?.[1]) return m[1];
1616
- }
1617
- const url = f.data instanceof URL ? f.data.href : typeof f.data === "string" ? f.data : "";
1618
- if (HTTP_RE.test(url) || f.name) {
1619
- const ext = (f.name ?? new URL(url, "http://x").pathname).split(".").pop()?.toLowerCase();
1620
- if (ext === "pdf") return "application/pdf";
1621
- if (ext && ["png", "jpg", "jpeg", "gif", "webp"].includes(ext)) {
1622
- return `image/${ext === "jpg" ? "jpeg" : ext}`;
1623
- }
1624
- }
1625
- return void 0;
1626
- };
1627
- var attachmentKind = (f) => {
1628
- const mt = mediaTypeOf(f) ?? "";
1629
- if (mt.startsWith("image/")) return "image";
1630
- if (mt === "application/pdf") return "pdf";
1631
- return "file";
1632
- };
1633
- var KIND_LABEL = {
1634
- image: "images",
1635
- pdf: "PDF files",
1636
- file: "file attachments"
1637
- };
1638
- var KIND_HINT = {
1639
- image: "Remove the image, or switch to a vision-capable model such as Gemini, Claude or GPT-4o/GPT-5.",
1640
- pdf: "Convert the PDF to text first (e.g. PDF \u2192 Markdown), or switch to a model that reads PDFs such as Gemini, Claude or GPT-4o/GPT-5.",
1641
- file: "Paste its text instead, or switch to a model that accepts this file type."
1642
- };
1643
- var AttachmentsNotSupportedError = class extends Error {
1644
- kind;
1645
- constructor(model, kind, detail) {
1646
- super(
1647
- `The model "${model}" can't take ${KIND_LABEL[kind]}${detail ? ` (${detail})` : ""}. ${KIND_HINT[kind]}`
1648
- );
1649
- this.name = "AttachmentsNotSupportedError";
1650
- this.kind = kind;
1651
- }
1652
- toJSON() {
1653
- return this.message;
1654
- }
1655
- };
1656
- var ImagesNotSupportedError = class extends AttachmentsNotSupportedError {
1657
- constructor(model, detail) {
1658
- super(model, "image", detail);
1659
- this.name = "ImagesNotSupportedError";
1660
- }
1661
- };
1662
- var unsupportedAttachment = (model, kind, detail) => kind === "image" ? new ImagesNotSupportedError(model, detail) : new AttachmentsNotSupportedError(model, kind, detail);
1663
- var dataOf = (f) => {
1664
- if (typeof f.data === "string") {
1665
- const m = DATA_URL_RE.exec(f.data);
1666
- if (m) return m[2];
1667
- if (HTTP_RE.test(f.data)) return new URL(f.data);
1668
- }
1669
- return f.data;
1670
- };
1671
- var toFilePart = (f) => {
1672
- const kind = attachmentKind(f);
1673
- const mediaType = mediaTypeOf(f) ?? (kind === "image" ? "image" : "application/octet-stream");
1674
- return {
1675
- type: "file",
1676
- data: dataOf(f),
1677
- mediaType,
1678
- ...f.name ? { filename: f.name } : {}
1679
- };
1680
- };
1681
- var toImagePart = toFilePart;
1682
- var modelLabel = (model) => {
1683
- if (typeof model === "string") return model;
1684
- const m = model;
1685
- return m?.modelId ? `${m.modelId}${m.provider ? ` (${m.provider})` : ""}` : "this model";
1686
- };
1687
- var REFUSAL_RE = /image|vision|multimodal|multi-modal|media type|mediatype|pdf|document|unsupported (file|content|part|mime)|does not support (file|content)|invalid content type|image_url|inline_?data|file_?data/i;
1688
- var isAttachmentRefusal = (err) => REFUSAL_RE.test(err instanceof Error ? `${err.name} ${err.message}` : String(err));
1689
- var isImageRefusal = isAttachmentRefusal;
1690
-
1691
1504
  // src/agent/internal.ts
1692
1505
  var promptFor = (ctx, prompt) => ctx.images?.length ? {
1693
1506
  messages: [
@@ -1811,7 +1624,7 @@ var executeStep = async (ctx, goal, step, index, total, done) => {
1811
1624
  }
1812
1625
  }
1813
1626
  }).catch((err) => {
1814
- throw imageRefusal(ctx, err, ctx.executorModel) ?? err;
1627
+ throw imageRefusal(ctx, err, ctx.executorModel) ?? contextOverflowOf(err, ctx.executorModel) ?? err;
1815
1628
  });
1816
1629
  ctx.log.debug("executor text:", loop.text);
1817
1630
  const { summary, blocked } = splitBlocker(loop.text);
@@ -1935,12 +1748,14 @@ ${nudge}` : goal;
1935
1748
  if (ctx.signal?.aborted) throw err;
1936
1749
  const refused = imageRefusal(ctx, err, ctx.plannerModel);
1937
1750
  if (refused) throw refused;
1751
+ const overflow = contextOverflowOf(err, ctx.plannerModel);
1752
+ if (overflow) throw overflow;
1938
1753
  ctx.log.warn("planner: native structured output failed, salvaging:", asMessage(err));
1939
1754
  ctx.emit({ type: "retry", phase: "plan", attempt: 1, error: asMessage(err) });
1940
1755
  }
1941
1756
  }
1942
1757
  const result = await generate(ctx.plannerModel, commonFor("prompted")).catch((err) => {
1943
- throw imageRefusal(ctx, err, ctx.plannerModel) ?? err;
1758
+ throw imageRefusal(ctx, err, ctx.plannerModel) ?? contextOverflowOf(err, ctx.plannerModel) ?? err;
1944
1759
  });
1945
1760
  const parsed = parsePlannerResponse(result.text);
1946
1761
  ctx.log.debug("planner (prompted) raw:", result.text);
@@ -2035,7 +1850,7 @@ var synthesizeAnswer = async (ctx, goal, done, findings = []) => {
2035
1850
  }
2036
1851
  if (part.type === "error") {
2037
1852
  const err = part.error instanceof Error ? part.error : new Error(String(part.error));
2038
- throw imageRefusal(ctx, err, ctx.synthesizerModel) ?? err;
1853
+ throw imageRefusal(ctx, err, ctx.synthesizerModel) ?? contextOverflowOf(err, ctx.synthesizerModel) ?? err;
2039
1854
  }
2040
1855
  if (part.type !== "text-delta") continue;
2041
1856
  const delta = part.text;
@@ -2093,10 +1908,11 @@ var CLOUD = /* @__PURE__ */ new Set([
2093
1908
  ]);
2094
1909
  var supportsNativeTools = (p) => CLOUD.has(p);
2095
1910
  var supportsStructuredOutput = (p) => CLOUD.has(p);
2096
- var directBrowserOk = (p) => p === "google" || p === "gateway" || p === "openai-compatible" || p === "anthropic";
1911
+ var directBrowserOk = (p) => p !== "web-llm";
2097
1912
  var LOCAL_RE2 = /web-?llm|mlc|browser-ai|transformers|built-?in/i;
1913
+ var LOCAL_VISION_RE = /vision|[-_]vl\b|[-_]vl[-_]|llava|smolvlm|moondream|gemma-?3n/i;
2098
1914
  var TEXT_ONLY_MODEL_RE = /gpt-3\.5|o1-mini|o3-mini|deepseek|text-(davinci|embedding)|embedding|babbage|davinci|codestral/i;
2099
- var VISION_PROVIDER_RE = /^(google|anthropic|openai|azure|xai|vertex|bedrock|gemini)/i;
1915
+ var VISION_PROVIDER_RE = /^(google|anthropic|openai|azure|xai|vertex|bedrock|gemini|moonshot|mistral)/i;
2100
1916
  var PDF_PROVIDER_RE = /^(google|anthropic|openai|azure|vertex|bedrock|gemini)/i;
2101
1917
  var supportsImages = (model) => {
2102
1918
  if (typeof model === "string") {
@@ -2107,14 +1923,16 @@ var supportsImages = (model) => {
2107
1923
  if (!model || typeof model !== "object") return void 0;
2108
1924
  const provider = String(model.provider ?? "");
2109
1925
  const id = String(model.modelId ?? "");
2110
- if (LOCAL_RE2.test(provider)) return false;
2111
- if (/deepseek/i.test(provider) || TEXT_ONLY_MODEL_RE.test(id)) return false;
1926
+ if (LOCAL_RE2.test(provider)) return LOCAL_VISION_RE.test(id);
1927
+ if (/deepseek/i.test(provider)) return /flash/i.test(id);
1928
+ if (TEXT_ONLY_MODEL_RE.test(id)) return false;
2112
1929
  return VISION_PROVIDER_RE.test(provider) ? true : void 0;
2113
1930
  };
2114
1931
  var supportsPdf = (model) => {
2115
1932
  const vision = supportsImages(model);
2116
1933
  if (vision === false) return false;
2117
1934
  const provider = typeof model === "string" ? model.split("/")[0] ?? "" : String(model?.provider ?? "");
1935
+ if (LOCAL_RE2.test(provider) || /moonshot/i.test(provider)) return false;
2118
1936
  return PDF_PROVIDER_RE.test(provider) ? true : void 0;
2119
1937
  };
2120
1938
 
@@ -2151,6 +1969,10 @@ var createAgent = async (config) => {
2151
1969
  ]);
2152
1970
  const plannerMode = selectToolMode(plannerModel, cfg.toolMode);
2153
1971
  const executorMode = selectToolMode(executorModel, cfg.toolMode);
1972
+ const modelWindows = [executorModel, plannerModel, synthesizerModel].map(contextWindowOf).filter((w) => w !== void 0);
1973
+ const modelWindow = modelWindows.length ? Math.min(...modelWindows) : void 0;
1974
+ cfg.compaction = fitCompactionToWindow(cfg.compaction, config.compaction, modelWindow);
1975
+ const byTokens = Boolean(config.compaction) || modelWindow !== void 0;
2154
1976
  const baseTools = filterTools(
2155
1977
  config.tools ?? {},
2156
1978
  config.availableTools,
@@ -2163,7 +1985,8 @@ var createAgent = async (config) => {
2163
1985
  skillNames.add(s.name);
2164
1986
  }
2165
1987
  const catalog = toolCatalogOf(baseTools);
2166
- const strategy = cfg.toolSelectionStrategy === "auto" ? catalog.length > cfg.toolSearchThreshold ? "search" : "all" : cfg.toolSelectionStrategy;
1988
+ const toolTokens = cfg.toolSelectionStrategy === "auto" ? await toolDefinitionTokens(baseTools) : 0;
1989
+ const strategy = cfg.toolSelectionStrategy === "auto" ? catalog.length > cfg.toolSearchThreshold || toolTokens > cfg.compaction.contextWindowTokens * TOOL_SEARCH_WINDOW_SHARE ? "search" : "all" : cfg.toolSelectionStrategy;
2167
1990
  const reserved = [
2168
1991
  ...skills.length ? SKILL_TOOL_NAMES : [],
2169
1992
  ...strategy === "search" ? [FIND_TOOLS_NAME] : []
@@ -2189,14 +2012,15 @@ var createAgent = async (config) => {
2189
2012
  const caching = resolveCaching(config.promptCaching);
2190
2013
  const textOnly = executorMode === "prompted";
2191
2014
  const accepts = {
2192
- image: config.inputs?.images ?? config.vision ?? (textOnly ? false : supportsImages(executorModel)),
2015
+ // A local vision model (the prompted path carries images too) says so by its id.
2016
+ image: config.inputs?.images ?? config.vision ?? (textOnly ? supportsImages(executorModel) === true : supportsImages(executorModel)),
2193
2017
  pdf: config.inputs?.pdf ?? (textOnly ? false : supportsPdf(executorModel)),
2194
2018
  file: config.inputs?.files ?? (textOnly ? false : void 0)
2195
2019
  };
2196
2020
  const approval = createApprovalState(config.toolApproval);
2197
2021
  const log = createLogger(cfg.logLevel, config.logger);
2198
2022
  log.info(
2199
- `agent ready \u2014 ${catalog.length} tool(s) (${strategy}), skills: [${[...skillNames].join(", ") || "none"}], planner mode: ${plannerMode}, executor mode: ${executorMode}, approval: ${approval.mode}`
2023
+ `agent ready \u2014 ${catalog.length} tool(s) (${strategy}, ~${toolTokens || "?"} tokens), window ${cfg.compaction.contextWindowTokens}${modelWindow ? " (the model\u2019s)" : ""}, skills: [${[...skillNames].join(", ") || "none"}], planner mode: ${plannerMode}, executor mode: ${executorMode}, approval: ${approval.mode}`
2200
2024
  );
2201
2025
  const run = async (goal, opts = {}) => {
2202
2026
  const emit = (event) => {
@@ -2307,7 +2131,7 @@ var createAgent = async (config) => {
2307
2131
  } catch {
2308
2132
  }
2309
2133
  }
2310
- if (config.memory && config.compaction && cfg.compaction.auto && history.length > 0) {
2134
+ if (config.memory && byTokens && cfg.compaction.auto && history.length > 0) {
2311
2135
  const before = messageTokens(history);
2312
2136
  if (before > cfg.compaction.thresholdTokens) {
2313
2137
  const compacted = await compressHistory(history, synthesizerModel, {
@@ -2519,7 +2343,8 @@ var createAgent = async (config) => {
2519
2343
  }
2520
2344
  }
2521
2345
  if (isAborted()) return stop();
2522
- let summary = "Done \u2014 the changes have been applied.";
2346
+ const stepWords = result.trace.map((r) => r.summary.trim()).filter((t) => t && !/^(Executed \d+ tool call\(s\)\.|Step produced no output\.)$/.test(t));
2347
+ let summary = stepWords.length ? stepWords.join("\n\n") : "Done \u2014 the changes have been applied.";
2523
2348
  if (cfg.synthesize) {
2524
2349
  try {
2525
2350
  const synth = await synthesizeAnswer(ctx, text, done, findings);
@@ -2534,12 +2359,12 @@ var createAgent = async (config) => {
2534
2359
  emit({ type: "final", text: summary });
2535
2360
  await remember({ role: "assistant", content: summary });
2536
2361
  result.final = summary;
2537
- if (config.memory && (config.compaction ? cfg.compaction.auto : cfg.compressAfterChars > 0)) {
2362
+ if (config.memory && (byTokens ? cfg.compaction.auto : cfg.compressAfterChars > 0)) {
2538
2363
  try {
2539
2364
  const transcript = await config.memory.load(sessionId);
2540
2365
  const before = messageTokens(transcript);
2541
2366
  const compacted = await compressHistory(transcript, synthesizerModel, {
2542
- ...config.compaction ? {
2367
+ ...byTokens ? {
2543
2368
  thresholdTokens: cfg.compaction.thresholdTokens,
2544
2369
  keepRecent: cfg.compaction.keepRecentTurns,
2545
2370
  summaryMaxTokens: cfg.budgets.compaction
@@ -2611,6 +2436,7 @@ var createAgent = async (config) => {
2611
2436
  },
2612
2437
  listTools: () => catalog.map((e) => ({ ...e })),
2613
2438
  toolStrategy: strategy,
2439
+ contextWindowTokens: cfg.compaction.contextWindowTokens,
2614
2440
  skills: skills.map((s) => ({ name: s.name, description: s.description })),
2615
2441
  capabilities: { images: accepts.image, pdf: accepts.pdf, files: accepts.file },
2616
2442
  models: { planner: plannerModel, executor: executorModel, synthesizer: synthesizerModel }
@@ -3270,6 +3096,7 @@ var IndexedDBStore = class {
3270
3096
  };
3271
3097
  export {
3272
3098
  AttachmentsNotSupportedError,
3099
+ ContextWindowExceededError,
3273
3100
  FILES_STORE,
3274
3101
  FIND_TOOLS_NAME,
3275
3102
  ImagesNotSupportedError,
@@ -3285,10 +3112,12 @@ export {
3285
3112
  SESSIONS_STORE,
3286
3113
  SKILL_TOOL_NAMES,
3287
3114
  TOOL_APPROVAL_MODES,
3115
+ TOOL_SEARCH_WINDOW_SHARE,
3288
3116
  ToolBudgetError,
3289
3117
  ToolDeniedError,
3290
3118
  VaultCredentialStore,
3291
3119
  VirtualFileSystem,
3120
+ WEBLLM_DEFAULT_CONTEXT_WINDOW,
3292
3121
  attachmentKind,
3293
3122
  buildModelFromStage,
3294
3123
  bytesToBase64,
@@ -3296,6 +3125,8 @@ export {
3296
3125
  compactHistory,
3297
3126
  compactSteps,
3298
3127
  compressHistory,
3128
+ contextOverflowOf,
3129
+ contextWindowOf,
3299
3130
  createAgent,
3300
3131
  createFileTools,
3301
3132
  createFindToolsTool,
@@ -3317,6 +3148,7 @@ export {
3317
3148
  messageTokens as estimateMessagesTokens,
3318
3149
  estimateTokens,
3319
3150
  executeStep,
3151
+ fitCompactionToWindow,
3320
3152
  generate,
3321
3153
  generateStructured,
3322
3154
  getOrCreateVaultKey,
@@ -3375,9 +3207,12 @@ export {
3375
3207
  toImagePart,
3376
3208
  tokenize,
3377
3209
  toolCatalogOf,
3210
+ toolDefinitionTokens,
3378
3211
  toolRunContextOf,
3379
3212
  unloadWebLLMModel,
3213
+ webLLMContextWindow,
3380
3214
  withRollingBreakpoint,
3381
- withSystem
3215
+ withSystem,
3216
+ withWebLLMContextWindow
3382
3217
  };
3383
3218
  //# sourceMappingURL=index.js.map