koneck 2.128.0 → 2.128.2

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
@@ -14,7 +14,7 @@ import { findChurn, describeChurn, WINDOW as CHURN_WINDOW } from './cycle.js';
14
14
  import { readingWithoutActing, describeReading } from './reading.js';
15
15
  import { claim, release, describeClaims } from './claims.js';
16
16
  import { handoffFrom, describeHandoff, worthSaying } from './handoff.js';
17
- import { readAll as readLedger, relevant as relevantFindings, withStaleness, describeFindings, deriveFindings, record as recordFindings, changedSince, currentSha } from './ledger.js';
17
+ import { readAll as readLedger, relevant as relevantFindings, withStaleness, describeFindings, deriveFindings, freshFindings, record as recordFindings, changedSince, currentSha } from './ledger.js';
18
18
  import { repoNameFor } from './session-bus.js';
19
19
  import { compressIfNeeded } from './compressor.js';
20
20
  import { contextLimitFor, looksLikeContextOverflow, parseContextLimit, fetchModelContextLimit, ollamaServingLimit, fixedRequestTokens, overheadIsCrowded, crowdedWindowAdvice, probeServedContext, detectWindowPlateau, truncationNotice, windowFixFor, windowSettingIgnored, runsOnThisMachine, } from './context-limit.js';
@@ -970,7 +970,7 @@ delegated) {
970
970
  // Live state for every agent, shared with the UI. It is mutated in place and republished on
971
971
  // each change, so a panel can show tokens climbing per agent rather than only a final count.
972
972
  const progress = tasks.map((task, index) => ({
973
- index, task, status: 'running', tokens: 0, turns: 0, startedAt: Date.now(),
973
+ index, task, status: 'running', activity: 'Queued', tokens: 0, turns: 0, startedAt: Date.now(),
974
974
  }));
975
975
  const publish = () => config.onAgentProgress?.(progress.map(p => ({ ...p })));
976
976
  publish();
@@ -992,10 +992,15 @@ delegated) {
992
992
  */
993
993
  if (abortSignal?.aborted) {
994
994
  mine.status = 'failed';
995
+ mine.activity = 'Cancelled before starting';
996
+ mine.endedAt = Date.now();
995
997
  publish();
996
998
  return { task, success: false,
997
999
  output: 'NOT RUN: stopped at the user\'s request before this agent started.' };
998
1000
  }
1001
+ mine.activity = 'Starting';
1002
+ mine.startedAt = Date.now();
1003
+ publish();
999
1004
  let taskCwd = cwd;
1000
1005
  let branch;
1001
1006
  if (isGit && args.use_worktrees !== false) {
@@ -1019,9 +1024,19 @@ delegated) {
1019
1024
  maxTurns: args.max_turns ?? resolveMaxTurns(config.maxTurns) ?? SUBAGENT_DEFAULT_TURNS,
1020
1025
  // A sub-agent must not stream its narration or tool calls into the parent's transcript —
1021
1026
  // eight agents writing at once is unreadable. Only its counters are forwarded.
1022
- onChunk: undefined,
1023
- onToolCall: undefined,
1024
- onToolResult: undefined,
1027
+ onChunk: () => { if (mine.activity !== 'Writing response') {
1028
+ mine.activity = 'Writing response';
1029
+ publish();
1030
+ } },
1031
+ onToolCall: (name, args) => { mine.activity = name + ': ' + toolDetailFor(name, args); publish(); },
1032
+ onToolResult: () => { mine.activity = 'Waiting for model'; publish(); },
1033
+ onToolOutput: undefined,
1034
+ onStreamActivity: undefined,
1035
+ onHandoff: undefined,
1036
+ onThinking: () => { if (mine.activity !== 'Thinking') {
1037
+ mine.activity = 'Thinking';
1038
+ publish();
1039
+ } },
1025
1040
  onAgentProgress: undefined,
1026
1041
  onTokens: (s) => {
1027
1042
  // Reported cumulatively per agent, so the parent is given the difference.
@@ -1062,8 +1077,9 @@ delegated) {
1062
1077
  ? full.slice(0, SUBAGENT_REPORT_CHARS) + `\n … (${full.length - SUBAGENT_REPORT_CHARS} more characters)`
1063
1078
  : full)
1064
1079
  : '(finished without saying anything)';
1065
- settle('done');
1066
- return { task, output, success: true, branch };
1080
+ const success = session.completed;
1081
+ settle(success ? 'done' : 'failed');
1082
+ return { task, output, success, branch };
1067
1083
  }
1068
1084
  catch (err) {
1069
1085
  settle('failed');
@@ -3535,10 +3551,10 @@ detectedContext = { current: 0 }) {
3535
3551
  */
3536
3552
  export function imagesMentionedIn(text, cwd) {
3537
3553
  const out = [];
3538
- for (const raw of text.split(/\s+/)) {
3554
+ for (const raw of text.match(/"[^"\n]+"|'[^'\n]+'|[^\s]+/g) ?? []) {
3539
3555
  // The question mark matters: "What is in swatch.png?" is how anyone actually asks, and
3540
3556
  // without it the token is `swatch.png?`, which has no extension we recognise.
3541
- const token = raw.replace(/[),.;:!?'"\]]+$/, '');
3557
+ const token = raw.replace(/^["']|[),.;:!?'"\]]+$/g, '');
3542
3558
  if (!imageMime(token))
3543
3559
  continue;
3544
3560
  const abs = path.isAbsolute(token) ? token : path.resolve(cwd, token);
@@ -3797,6 +3813,7 @@ initialPlan) {
3797
3813
  // Images named in the prompt are sent as images. Naming a screenshot used to do nothing at
3798
3814
  // all: the model got the path, could not open a PNG, and answered about a file it had never
3799
3815
  // seen — while the person asking was looking straight at it.
3816
+ const trajectoryBefore = new Set(trajectory.all());
3800
3817
  const named = imagePaths?.length ? [...imagePaths] : imagesMentionedIn(userText, config.cwd);
3801
3818
  const { images, problems } = named.length ? await loadImages(named) : { images: [], problems: [] };
3802
3819
  for (const problem of problems) {
@@ -3848,10 +3865,11 @@ initialPlan) {
3848
3865
  */
3849
3866
  try {
3850
3867
  const sha = await currentSha(config.cwd);
3851
- const learned = deriveFindings(trajectory?.all() ?? [], {
3868
+ const turnEvents = trajectory.all().filter(event => !trajectoryBefore.has(event));
3869
+ const learned = freshFindings(deriveFindings(turnEvents, {
3852
3870
  ...(sha ? { sha } : {}),
3853
3871
  ...(config.sessionLabel ? { session: config.sessionLabel } : {}),
3854
- });
3872
+ }), await readLedger(config.cwd));
3855
3873
  if (learned.length > 0)
3856
3874
  await recordFindings(config.cwd, learned);
3857
3875
  /*
@@ -3861,7 +3879,7 @@ initialPlan) {
3861
3879
  * it are already kept — the ledger has the findings and the transcript has the rest. What
3862
3880
  * was missing was anybody saying the three things out loud at the moment they are true.
3863
3881
  */
3864
- const note = handoffFrom(trajectory?.all() ?? [], planRef.current.steps, learned);
3882
+ const note = handoffFrom(turnEvents, planRef.current.steps, learned.filter(f => f.kind !== 'timing'));
3865
3883
  if (worthSaying(note)) {
3866
3884
  const said = describeHandoff(note);
3867
3885
  if (said)