koneck 2.98.0 → 2.100.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/engine.js CHANGED
@@ -17,7 +17,7 @@ import { handoffFrom, describeHandoff, worthSaying } from './handoff.js';
17
17
  import { readAll as readLedger, relevant as relevantFindings, withStaleness, describeFindings, deriveFindings, record as recordFindings, changedSince, currentSha } from './ledger.js';
18
18
  import { repoNameFor } from './session-bus.js';
19
19
  import { compressIfNeeded } from './compressor.js';
20
- import { contextLimitFor, looksLikeContextOverflow, parseContextLimit, fetchModelContextLimit, ollamaServingLimit, fixedRequestTokens, overheadIsCrowded, crowdedWindowAdvice, probeOllamaContext, detectWindowPlateau, truncationNotice, ollamaWindowFix, runsOnThisMachine, } from './context-limit.js';
20
+ import { contextLimitFor, looksLikeContextOverflow, parseContextLimit, fetchModelContextLimit, ollamaServingLimit, fixedRequestTokens, overheadIsCrowded, crowdedWindowAdvice, probeServedContext, detectWindowPlateau, truncationNotice, windowFixFor, windowSettingIgnored, runsOnThisMachine, } from './context-limit.js';
21
21
  import { generateSessionId, saveSession } from './session.js';
22
22
  import { EMPTY_PLAN, parsePlan, planReminder, planAck, noPlanReminder } from './plan.js';
23
23
  import { spillIfOversized } from './spill.js';
@@ -1143,7 +1143,15 @@ export function emptyResponseAdvice(provider, model, count, toolsWorked, endpoin
1143
1143
  * session with skills loaded is larger again. Quoting a constant is asserting something not
1144
1144
  * known, and it is the number somebody uses to decide what to set the window to.
1145
1145
  */
1146
- fixedTokens, platform) {
1146
+ fixedTokens, platform,
1147
+ /**
1148
+ * Which runtime was measured to be serving. Decides which fix is named.
1149
+ *
1150
+ * `served`, not `runtime`: there is already a boolean called that a few lines down, meaning
1151
+ * "is this a thing that serves its own weights at all" — a different question with a confusingly
1152
+ * similar name.
1153
+ */
1154
+ served) {
1147
1155
  // The endpoint is named, not just the provider slot. Reported as "omni returned 3 empty
1148
1156
  // responses ... yet i am using ollama" — both true at once, because the endpoint saved under the
1149
1157
  // omni slot is an Ollama box. Naming the address answers the objection in the message itself.
@@ -1175,7 +1183,7 @@ fixedTokens, platform) {
1175
1183
  'truncates a longer prompt instead of refusing it — and KONECK\'s instructions and tool ' +
1176
1184
  `descriptions come to ${cost} before your conversation is counted, which is exactly ` +
1177
1185
  'how a turn comes back with nothing in it.\n\n' +
1178
- ollamaWindowFix({ ...(endpoint !== undefined ? { endpoint } : {}), remote,
1186
+ windowFixFor(served ?? null, { ...(endpoint !== undefined ? { endpoint } : {}), remote,
1179
1187
  ...(platform !== undefined ? { platform } : {}) }) +
1180
1188
  '\n\nIf you know the real limit, `/config contextTokens <n>` makes KONECK compact before ' +
1181
1189
  'reaching it.';
@@ -1619,6 +1627,9 @@ detectedContext = { current: 0 }) {
1619
1627
  // sends someone to restart the wrong one.
1620
1628
  // Loopback means this machine; a LAN address is somebody else's. See runsOnThisMachine.
1621
1629
  remote: !runsOnThisMachine(resolveProvider(config.provider, config.baseURL).baseURL),
1630
+ // Measured, when it could be: it decides whether the steps name OLLAMA_CONTEXT_LENGTH, -c,
1631
+ // a Context Length slider or --max-model-len.
1632
+ runtime: config.servedRuntime ?? null,
1622
1633
  });
1623
1634
  if (sayOnce) {
1624
1635
  // One block, in the order somebody reads it: what the window is and whose it is, then what
@@ -1973,6 +1984,7 @@ detectedContext = { current: 0 }) {
1973
1984
  // Whether the thing to reconfigure is this machine or another one. KONECK knows its
1974
1985
  // own platform and nothing about a remote box, so a remote answer names no commands.
1975
1986
  remote: !runsOnThisMachine(endpoint),
1987
+ runtime: config.servedRuntime ?? null,
1976
1988
  });
1977
1989
  config.onTruncation?.(plateau.window, said);
1978
1990
  if (!silent)
@@ -2487,7 +2499,7 @@ detectedContext = { current: 0 }) {
2487
2499
  const endpoint = resolveProvider(config.provider, config.baseURL).baseURL;
2488
2500
  const noRoom = fixedCost > 0 && overheadIsCrowded(fixedCost, effectiveLimit());
2489
2501
  if (noRoom) {
2490
- const notice = deniedBecauseNoRoom(denied, config.model, fixedCost, effectiveLimit(), ollamaWindowFix({ endpoint, remote: !runsOnThisMachine(endpoint) }));
2502
+ const notice = deniedBecauseNoRoom(denied, config.model, fixedCost, effectiveLimit(), windowFixFor(config.servedRuntime ?? null, { endpoint, remote: !runsOnThisMachine(endpoint) }));
2491
2503
  config.onFalseDenial?.(denied.map(d => d.what), notice);
2492
2504
  if (!silent)
2493
2505
  tui.printWarning(notice);
@@ -2649,7 +2661,7 @@ detectedContext = { current: 0 }) {
2649
2661
  // likely cause.
2650
2662
  throw new Error(emptyResponseAdvice(config.provider, config.model, emptyTurns, toolsProvenToWork, resolveProvider(config.provider, config.baseURL).baseURL,
2651
2663
  // The floor this run actually has, rather than a constant in a string.
2652
- fixedCost));
2664
+ fixedCost, undefined, config.servedRuntime));
2653
2665
  }
2654
2666
  }
2655
2667
  else {
@@ -3328,7 +3340,21 @@ initialPlan) {
3328
3340
  // provider slot called "omni" is still served by Ollama, and while this asked about the name
3329
3341
  // that setup got neither the smaller window nor a word of warning.
3330
3342
  const locallyServed = servesLocally(config.provider, resolveProvider(config.provider, config.baseURL).baseURL);
3331
- if (!config.contextTokens && locallyServed) {
3343
+ /*
3344
+ * The configured window is asked about too, not only an absent one.
3345
+ *
3346
+ * This ran `if (!config.contextTokens)`, so setting the window in KONECK *skipped the
3347
+ * measurement*. Which turns the setting into a trap on exactly the machine that needs it most:
3348
+ * somebody told to raise Ollama's window reads "Context window — the model's context window, when
3349
+ * you know it better than KONECK does", sets 32768 there, and KONECK then believes it and builds
3350
+ * prompts up to 24k. Ollama is still serving 4,096 and still truncates silently, so the result is
3351
+ * worse than before — empty turns, and a model insisting it has no browser.
3352
+ *
3353
+ * A number typed here cannot make a server accept more than it will. So it can lower the limit —
3354
+ * that is a legitimate thing to want, and compaction happens earlier — but never raise it past
3355
+ * what the server reports.
3356
+ */
3357
+ if (locallyServed) {
3332
3358
  // Asked, not assumed. KONECK took Ollama's 4,096 default as fact for anything served locally,
3333
3359
  // so a server running with a larger window was being compacted and trimmed for a limit that
3334
3360
  // did not exist. The objection was fair: nothing should be limited that does not have to be.
@@ -3337,11 +3363,39 @@ initialPlan) {
3337
3363
  // is built — and bounded, so an endpoint that does not answer costs a second rather than a
3338
3364
  // timeout. It is a call to a machine on your own network.
3339
3365
  const endpoint = resolveProvider(config.provider, config.baseURL).baseURL;
3340
- const probed = await probeOllamaContext(endpoint, config.model);
3341
- if (probed) {
3342
- config = { ...config, contextTokens: probed.limit };
3366
+ /*
3367
+ * Every local runtime KONECK recognises, not only Ollama.
3368
+ *
3369
+ * Eleven count as serving their own weights and exactly one of them was ever measured, so
3370
+ * llama.cpp on `-c 2048` or LM Studio with a small slider got no window at all — the plateau
3371
+ * detector eventually notices, but only after three turns, and everything before that fails the
3372
+ * same silent way. The provider name is a hint about which endpoint to try first and nothing
3373
+ * more: a declared provider called "omni" pointing at an Ollama box is Ollama.
3374
+ */
3375
+ const probed = await probeServedContext(endpoint, config.model, { hint: config.provider });
3376
+ const asked = config.contextTokens ?? 0;
3377
+ if (probed && asked > 0 && probed.limit >= asked) {
3378
+ // A deliberate, smaller budget. Kept: nothing about it can fail, and earlier compaction is a
3379
+ // reasonable thing to choose.
3380
+ config.onWindowDetected?.(asked, 'your setting, within the server\'s ' + probed.limit);
3381
+ }
3382
+ else if (probed && asked > 0) {
3383
+ config = { ...config, servedRuntime: probed.runtime };
3384
+ // Asked for more than the server will give. The server's figure is the one that gets
3385
+ // enforced, so it wins — and the difference is said out loud, because a setting that is
3386
+ // quietly ignored is how somebody concludes the setting does not work.
3387
+ config = { ...config, contextTokens: probed.limit, servedRuntime: probed.runtime };
3388
+ config.onWindowConflict?.(asked, probed.limit, windowSettingIgnored(asked, probed.limit));
3343
3389
  config.onWindowDetected?.(probed.limit, probed.source);
3344
3390
  }
3391
+ else if (probed) {
3392
+ config = { ...config, contextTokens: probed.limit, servedRuntime: probed.runtime };
3393
+ config.onWindowDetected?.(probed.limit, probed.source);
3394
+ }
3395
+ else if (asked > 0) {
3396
+ // Nothing to compare against: the model is not loaded, so /api/ps has nothing to say about
3397
+ // it. The setting stands, which is what it is for.
3398
+ }
3345
3399
  else if (/localhost|127\.0\.0\.1|::1/.test(endpoint) && process.env['OLLAMA_CONTEXT_LENGTH']) {
3346
3400
  // Only for an endpoint on this machine. OLLAMA_CONTEXT_LENGTH is read by the Ollama server,
3347
3401
  // so this process's copy of it describes a server running here and says nothing whatever