@kenkaiiii/gg-boss 4.3.156 → 4.3.157

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.
@@ -49501,7 +49501,7 @@ var TOOL_PROMPT_HINTS = {
49501
49501
  tasks: "Manage the Ctrl+T task pane (add/list/done/remove). Only when the user explicitly asks. Do NOT auto-run.",
49502
49502
  subagent: "Delegate focused, isolated subtasks (research, parallel exploration).",
49503
49503
  skill: "Invoke a named skill for specialized instructions.",
49504
- mcp__grep__searchGitHub: "Search real-world code in 1M+ GitHub repos. Single literal pattern per call. Sequential only (rate-limited).",
49504
+ "mcp__kencode-search__searchCode": 'Literal-text or RE2-regex search across 2M+ public repos. NOT semantic. Have only a concept? Anchor on a literal token a matching file would contain \u2014 a library import (`from "remotion"`), a known identifier/hook/prop (`useVideoConfig`, `<Sequence`), or a config key. Filename + topic in `query` does NOT work \u2014 put filenames in `path`, topics in `repo`. Filters: `language: ["TypeScript"]`, `repo: "owner/name"`, `path: "src/components/"`. Workflow: `peek: true` \u2192 paths+counts; then narrow with `repo` + `path` for full snippets. Defaults exclude tests/vendored/generated \u2014 set `includeTests` or `includeVendored` to widen. RE2: no lookahead/lookbehind/backrefs; multi-line needs `(?s)`.',
49505
49505
  enter_plan: "Enter plan mode for read-only research + planning on complex multi-file tasks.",
49506
49506
  exit_plan: "Submit your plan for user review and exit plan mode."
49507
49507
  };
@@ -49519,7 +49519,7 @@ var DEFAULT_TOOL_NAMES = [
49519
49519
  "tasks",
49520
49520
  "subagent",
49521
49521
  "skill",
49522
- "mcp__grep__searchGitHub",
49522
+ "mcp__kencode-search__searchCode",
49523
49523
  "enter_plan",
49524
49524
  "exit_plan"
49525
49525
  ];
@@ -49558,7 +49558,7 @@ You are in PLAN MODE. Research and design an implementation plan before writing
49558
49558
 
49559
49559
  ### Workflow
49560
49560
  1. Explore: read, grep, find, ls to understand the codebase
49561
- 2. Research: web_search + web_fetch for docs, mcp__grep__searchGitHub for real code samples
49561
+ 2. Research: \`web_search\` + \`web_fetch\` for docs; \`mcp__kencode-search__searchCode\` for real code samples \u2014 literal text or RE2 regex (NOT semantic); start with \`peek: true\` for paths+counts, then drill in narrowed by \`repo\` + \`path\` (full usage in Research & Verification below)
49562
49562
  3. Draft: write the plan to .gg/plans/<name>.md
49563
49563
  4. Submit: call exit_plan with the plan path
49564
49564
 
@@ -49594,8 +49594,19 @@ ${planContent.trim()}
49594
49594
  Your training data may be outdated. Do not assume \u2014 verify.
49595
49595
 
49596
49596
  - **Docs first**: \`web_search\` \u2192 \`web_fetch\`.
49597
- - **Real code second**: \`mcp__grep__searchGitHub\` for patterns, UI, library usage, APIs.
49598
- - Applies to everything \u2014 APIs, CLI flags, configs, versions. Not just "unfamiliar" code.`);
49597
+ - **Real code second**: \`mcp__kencode-search__searchCode\` \u2014 literal-text or RE2-regex search across 2M+ public repos. **Not semantic.**
49598
+ - **Concept \u2192 query recipe.** If you only have a concept ("karaoke captions", "spring animation"), DO NOT search the concept. Anchor on a literal token a matching file would contain:
49599
+ 1. A library import \u2014 \`from "remotion"\`, \`import { spring }\`, \`from "@remotion/captions"\`
49600
+ 2. A known identifier/prop/hook \u2014 \`useVideoConfig\`, \`interpolate(\`, \`<Sequence\`, \`SubtitlePage\`
49601
+ 3. A unique config key \u2014 \`"defaultExport":\`, \`assetsInclude:\`
49602
+ Bad: \`karaoke word animation subtitle\` \u2192 zero hits, every time. Good: \`from "@remotion/captions"\` + \`peek: true\` \u2192 real files; then narrow with \`repo\` + \`path\` and read them.
49603
+ - **Filename + topic \u2260 query.** \`Page.tsx tiktok\` won't match. Use \`path: "Page.tsx"\` + \`repo: "remotion-dev"\` + a literal token in \`query\`.
49604
+ - Filters: \`language: ["TypeScript"]\`, \`repo: "owner/name"\` (substring), \`path: "src/components/"\` (substring), \`matchCase\`, \`useRegexp\`.
49605
+ - Workflow: \`peek: true\` first \u2192 paths + match counts only (cheap triage). Then call again narrowed by \`repo\` + \`path\` for full snippets. Paginate with \`offset\`.
49606
+ - Defaults exclude tests, \`node_modules\`, vendored, build, and generated files \u2014 pass \`includeTests: true\` or \`includeVendored: true\` to widen.
49607
+ - Token budget: \`maxResults\` defaults to 10 (cap 200), \`contextLines\` defaults to 5 (range 0\u201320). Keep both small unless you need more.
49608
+ - RE2 regex only: no lookahead/lookbehind/backrefs; multi-line patterns need \`(?s)\` prefix.
49609
+ - Applies to everything \u2014 APIs, CLI flags, configs (vite.config.ts, package.json, Dockerfile, GH Actions), shell idioms, schema shapes, error wording, conventions. Not just "unfamiliar" code.`);
49599
49610
  sections.push(`## Code Quality
49600
49611
 
49601
49612
  - Descriptive names that reveal intent. Define types before implementation.
@@ -51852,8 +51863,8 @@ var getRootConfigPath = async () => {
51852
51863
  if (configDir) {
51853
51864
  return configDir;
51854
51865
  }
51855
- const os9 = getPlatformHeaders()["X-Stainless-OS"];
51856
- if (os9 === "Windows") {
51866
+ const os10 = getPlatformHeaders()["X-Stainless-OS"];
51867
+ if (os10 === "Windows") {
51857
51868
  const appData = readEnv("APPDATA");
51858
51869
  if (appData) {
51859
51870
  return path30.join(appData, "Anthropic");
@@ -69035,10 +69046,10 @@ When all workers have reported, render the final table and a one-line summary (e
69035
69046
  {
69036
69047
  name: "compare",
69037
69048
  aliases: [],
69038
- description: "Compare code against real-world implementations via Grep MCP",
69039
- prompt: `Compare the code you just created or modified in this conversation against real-world implementations using the \`mcp__grep__searchGitHub\` tool.
69049
+ description: "Compare code against real-world implementations via kencode-search",
69050
+ prompt: `Compare the code you just created or modified in this conversation against real-world implementations using the \`mcp__kencode-search__searchCode\` tool.
69040
69051
 
69041
- You already know what you just built. For each file you created or modified, use \`mcp__grep__searchGitHub\` to search for how real projects implement the same patterns. Look at the specific APIs, hooks, functions, and architecture you used.
69052
+ You already know what you just built. For each file you created or modified, use \`mcp__kencode-search__searchCode\` to search for how real projects implement the same patterns. Look at the specific APIs, hooks, functions, and architecture you used.
69042
69053
 
69043
69054
  If you find something consistently done differently across real codebases, or something commonly included that you left out, report it:
69044
69055
 
@@ -69046,10 +69057,10 @@ If you find something consistently done differently across real codebases, or so
69046
69057
  [MISSING/DIVERGENT/INCOMPLETE] file:line - What it is
69047
69058
  Wrote: What was implemented
69048
69059
  Real-world: What real projects do instead/additionally
69049
- Evidence: Grep MCP - pattern seen in X out of Y repos searched
69060
+ Evidence: kencode-search - pattern seen in X out of Y repos searched
69050
69061
  \`\`\`
69051
69062
 
69052
- Style preferences and subjective improvements are not valid findings. Only report things backed by clear Grep MCP evidence across multiple repos.
69063
+ Style preferences and subjective improvements are not valid findings. Only report things backed by clear kencode-search evidence across multiple repos.
69053
69064
 
69054
69065
  If the code aligns well with real-world patterns, say so. That's a good outcome.`
69055
69066
  },
@@ -75398,6 +75409,7 @@ var StdioClientTransport = class {
75398
75409
  };
75399
75410
 
75400
75411
  // ../ggcoder/dist/core/mcp/client.js
75412
+ import os7 from "os";
75401
75413
  var MCPClientManager = class {
75402
75414
  servers = [];
75403
75415
  async connectAll(configs) {
@@ -75428,10 +75440,23 @@ var MCPClientManager = class {
75428
75440
  command: config2.command,
75429
75441
  args: config2.args,
75430
75442
  env: { ...process.env, ...config2.env },
75443
+ cwd: os7.homedir(),
75431
75444
  stderr: "pipe"
75432
75445
  });
75446
+ const stderrChunks = [];
75447
+ transport.stderr?.on("data", (chunk) => {
75448
+ stderrChunks.push(typeof chunk === "string" ? chunk : chunk.toString("utf8"));
75449
+ });
75433
75450
  client = new Client({ name: "ggcoder", version: "1.0.0" });
75434
- await client.connect(transport, { timeout });
75451
+ try {
75452
+ await client.connect(transport, { timeout });
75453
+ } catch (err) {
75454
+ const stderr = stderrChunks.join("").slice(-4e3);
75455
+ if (stderr.trim()) {
75456
+ log("WARN", "mcp", `stdio child stderr for "${config2.name}"`, { stderr });
75457
+ }
75458
+ throw err;
75459
+ }
75435
75460
  } else {
75436
75461
  const url2 = new URL(config2.url);
75437
75462
  const reqInit = config2.headers ? { headers: config2.headers } : void 0;
@@ -75515,7 +75540,7 @@ function createHeaderFetch(extraHeaders) {
75515
75540
  // ../ggcoder/dist/core/mcp/defaults.js
75516
75541
  init_esm_shims();
75517
75542
  var DEFAULT_MCP_SERVERS = [
75518
- { name: "grep", url: "https://mcp.grep.app" }
75543
+ { name: "kencode-search", command: "npx", args: ["-y", "@kenkaiiii/kencode-search"] }
75519
75544
  ];
75520
75545
  function getMCPServers(provider, apiKey) {
75521
75546
  const servers = [...DEFAULT_MCP_SERVERS];
@@ -76277,7 +76302,7 @@ __export(base_exports, {
76277
76302
  });
76278
76303
  init_esm_shims();
76279
76304
  import process4 from "process";
76280
- import os7 from "os";
76305
+ import os8 from "os";
76281
76306
 
76282
76307
  // ../../node_modules/.pnpm/environment@1.1.0/node_modules/environment/index.js
76283
76308
  init_esm_shims();
@@ -76377,7 +76402,7 @@ var isOldWindows = () => {
76377
76402
  if (isBrowser || !isWindows2) {
76378
76403
  return false;
76379
76404
  }
76380
- const parts = os7.release().split(".");
76405
+ const parts = os8.release().split(".");
76381
76406
  const major = Number(parts[0]);
76382
76407
  const build = Number(parts[2] ?? 0);
76383
76408
  if (major < 10) {
@@ -90692,7 +90717,7 @@ init_esm_shims();
90692
90717
  import { spawn as spawn5 } from "child_process";
90693
90718
  import fs25 from "fs";
90694
90719
  import path24 from "path";
90695
- import os8 from "os";
90720
+ import os9 from "os";
90696
90721
  var PACKAGE_NAME = "@kenkaiiii/ggcoder";
90697
90722
  var REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}/latest`;
90698
90723
  var CHECK_INTERVAL_MS = 1 * 60 * 60 * 1e3;
@@ -90808,6 +90833,48 @@ init_esm_shims();
90808
90833
  var import_react75 = __toESM(require_react(), 1);
90809
90834
  var nextId = 1;
90810
90835
  var id = () => `i${nextId++}`;
90836
+ var HISTORY_FULL_ITEMS = 1e3;
90837
+ var HISTORY_TRIM_MARKER = "\u2026(trimmed)\u2026";
90838
+ var historyTrimmedUpTo = 0;
90839
+ function trimItemFields(item) {
90840
+ switch (item.kind) {
90841
+ case "tool":
90842
+ if (item.result.length > 200) item.result = HISTORY_TRIM_MARKER;
90843
+ item.args = {};
90844
+ item.details = void 0;
90845
+ break;
90846
+ case "worker_event":
90847
+ if (item.finalText.length > 200) {
90848
+ item.finalText = item.finalText.slice(0, 200) + " " + HISTORY_TRIM_MARKER;
90849
+ }
90850
+ break;
90851
+ case "assistant":
90852
+ if (item.text.length > 200) item.text = item.text.slice(0, 200) + " " + HISTORY_TRIM_MARKER;
90853
+ if (item.thinking && item.thinking.length > 100) item.thinking = HISTORY_TRIM_MARKER;
90854
+ break;
90855
+ case "worker_error":
90856
+ if (item.message.length > 200) {
90857
+ item.message = item.message.slice(0, 200) + " " + HISTORY_TRIM_MARKER;
90858
+ }
90859
+ break;
90860
+ case "info":
90861
+ case "update_notice":
90862
+ if (item.text.length > 400) item.text = item.text.slice(0, 400) + " " + HISTORY_TRIM_MARKER;
90863
+ break;
90864
+ case "user":
90865
+ case "task_dispatch":
90866
+ break;
90867
+ }
90868
+ }
90869
+ function trimAgedHistory() {
90870
+ const cutoff = state.history.length - HISTORY_FULL_ITEMS;
90871
+ if (cutoff <= historyTrimmedUpTo) return;
90872
+ for (let i = historyTrimmedUpTo; i < cutoff; i++) {
90873
+ const item = state.history[i];
90874
+ if (item) trimItemFields(item);
90875
+ }
90876
+ historyTrimmedUpTo = cutoff;
90877
+ }
90811
90878
  function isText(p) {
90812
90879
  return p.type === "text";
90813
90880
  }
@@ -90885,6 +90952,7 @@ var bossStore = {
90885
90952
  workStartedAt: null
90886
90953
  }))
90887
90954
  };
90955
+ historyTrimmedUpTo = 0;
90888
90956
  notify();
90889
90957
  },
90890
90958
  setBossThinking(level) {
@@ -90908,6 +90976,7 @@ var bossStore = {
90908
90976
  ...state,
90909
90977
  history: [...state.history, { kind: "user", id: id(), text, timestamp: Date.now() }]
90910
90978
  };
90979
+ trimAgedHistory();
90911
90980
  notify();
90912
90981
  },
90913
90982
  appendTaskDispatch(tasks) {
@@ -90919,6 +90988,7 @@ var bossStore = {
90919
90988
  { kind: "task_dispatch", id: id(), tasks, timestamp: Date.now() }
90920
90989
  ]
90921
90990
  };
90991
+ trimAgedHistory();
90922
90992
  notify();
90923
90993
  },
90924
90994
  appendInfo(text, level = "info") {
@@ -90926,6 +90996,7 @@ var bossStore = {
90926
90996
  ...state,
90927
90997
  history: [...state.history, { kind: "info", id: id(), text, level }]
90928
90998
  };
90999
+ trimAgedHistory();
90929
91000
  notify();
90930
91001
  },
90931
91002
  /**
@@ -90939,6 +91010,7 @@ var bossStore = {
90939
91010
  ...state,
90940
91011
  history: [...state.history, { kind: "update_notice", id: id(), text }]
90941
91012
  };
91013
+ trimAgedHistory();
90942
91014
  notify();
90943
91015
  },
90944
91016
  /**
@@ -90966,6 +91038,7 @@ var bossStore = {
90966
91038
  history: [...state.history, ...newRows],
90967
91039
  pendingEndOfTurnInfos: []
90968
91040
  };
91041
+ trimAgedHistory();
90969
91042
  notify();
90970
91043
  },
90971
91044
  setPendingMessages(n) {
@@ -91168,6 +91241,7 @@ var bossStore = {
91168
91241
  history: [...state.history, ...state.pendingFlush],
91169
91242
  pendingFlush: []
91170
91243
  };
91244
+ trimAgedHistory();
91171
91245
  notify();
91172
91246
  },
91173
91247
  /**
@@ -91291,6 +91365,7 @@ var bossStore = {
91291
91365
  (w) => w.name === summary.project ? { ...w, status: summary.status, workStartedAt: null, lastSummary: summary } : w
91292
91366
  )
91293
91367
  };
91368
+ trimAgedHistory();
91294
91369
  notify();
91295
91370
  },
91296
91371
  appendWorkerError(project, message, timestamp) {
@@ -91301,6 +91376,7 @@ var bossStore = {
91301
91376
  (w) => w.name === project ? { ...w, status: "error", workStartedAt: null } : w
91302
91377
  )
91303
91378
  };
91379
+ trimAgedHistory();
91304
91380
  notify();
91305
91381
  },
91306
91382
  setScope(scope) {
@@ -91335,6 +91411,7 @@ var bossStore = {
91335
91411
  },
91336
91412
  reset() {
91337
91413
  state = initialState;
91414
+ historyTrimmedUpTo = 0;
91338
91415
  notify();
91339
91416
  },
91340
91417
  /**
@@ -91397,6 +91474,7 @@ var bossStore = {
91397
91474
  }
91398
91475
  }
91399
91476
  state = { ...state, history: [...state.history, ...items] };
91477
+ trimAgedHistory();
91400
91478
  notify();
91401
91479
  },
91402
91480
  /** /clear handler: wipe history but keep workers, model info, etc. */
@@ -91417,6 +91495,7 @@ var bossStore = {
91417
91495
  // the overlay it was invoked from.
91418
91496
  overlay: null
91419
91497
  };
91498
+ historyTrimmedUpTo = 0;
91420
91499
  notify();
91421
91500
  }
91422
91501
  };
@@ -91666,6 +91745,15 @@ var Worker = class {
91666
91745
  async switchModel(provider, model) {
91667
91746
  await this.session.switchModel(provider, model);
91668
91747
  }
91748
+ /**
91749
+ * Live ref to this worker's message array (NOT a copy). Used by the
91750
+ * orchestrator's post-turn truncation pass to mutate oversized tool
91751
+ * results in place — long-running workers accumulate huge `read` /
91752
+ * `bash` outputs in their history and that's the dominant heap consumer.
91753
+ */
91754
+ getMessagesRef() {
91755
+ return this.session.getMessages();
91756
+ }
91669
91757
  /**
91670
91758
  * Wipe this worker's conversation history and start a new session file.
91671
91759
  * Used by `prompt_worker(..., fresh: true)` when the boss declares the
@@ -92750,6 +92838,57 @@ function playReadyAudio() {
92750
92838
  return playFile(assetPath("ready.mp3"));
92751
92839
  }
92752
92840
 
92841
+ // src/truncate-tool-results.ts
92842
+ init_esm_shims();
92843
+ var DEFAULT_MAX_CHARS = 25e3;
92844
+ var TAIL_PROTECTED_MESSAGES = 6;
92845
+ var TRUNCATION_MARKER = "[[gg-boss:truncated]]";
92846
+ function buildNotice(originalLen, keptLen) {
92847
+ const omitted = originalLen - keptLen;
92848
+ return `
92849
+
92850
+ ${TRUNCATION_MARKER} ${omitted.toLocaleString()} of ${originalLen.toLocaleString()} characters omitted to control heap pressure. Re-run the tool if you need the full output.`;
92851
+ }
92852
+ function truncateString2(s, maxChars) {
92853
+ if (s.length <= maxChars) return null;
92854
+ if (s.includes(TRUNCATION_MARKER)) return null;
92855
+ return s.slice(0, maxChars) + buildNotice(s.length, maxChars);
92856
+ }
92857
+ function truncateToolResultContent(content, maxChars) {
92858
+ if (typeof content === "string") {
92859
+ const next = truncateString2(content, maxChars);
92860
+ return next === null ? { content, changed: false } : { content: next, changed: true };
92861
+ }
92862
+ let changed = false;
92863
+ const nextBlocks = content.map((block2) => {
92864
+ if (block2.type !== "text") return block2;
92865
+ const next = truncateString2(block2.text, maxChars);
92866
+ if (next === null) return block2;
92867
+ changed = true;
92868
+ return { ...block2, text: next };
92869
+ });
92870
+ return { content: changed ? nextBlocks : content, changed };
92871
+ }
92872
+ function truncateOversizedToolResults(messages, opts = {}) {
92873
+ const maxChars = opts.maxChars ?? DEFAULT_MAX_CHARS;
92874
+ const tailProtected = opts.tailProtected ?? TAIL_PROTECTED_MESSAGES;
92875
+ const cutoff = Math.max(0, messages.length - tailProtected);
92876
+ let truncated = 0;
92877
+ for (let i = 0; i < cutoff; i++) {
92878
+ const msg = messages[i];
92879
+ if (!msg || msg.role !== "tool") continue;
92880
+ for (const block2 of msg.content) {
92881
+ if (block2.isError) continue;
92882
+ const { content, changed } = truncateToolResultContent(block2.content, maxChars);
92883
+ if (changed) {
92884
+ block2.content = content;
92885
+ truncated += 1;
92886
+ }
92887
+ }
92888
+ }
92889
+ return truncated;
92890
+ }
92891
+
92753
92892
  // src/sessions.ts
92754
92893
  init_esm_shims();
92755
92894
  import fs30 from "fs/promises";
@@ -93133,6 +93272,31 @@ var GGBoss = class {
93133
93272
  * Append any boss messages that haven't been written yet to the session log.
93134
93273
  * Skips the system message (regenerated each session from current project list).
93135
93274
  */
93275
+ /**
93276
+ * Walk boss + every worker message array and truncate oversized
93277
+ * tool_result content. In-place mutation — propagates back through
93278
+ * `Agent.getMessages()` shared references. Called once per boss
93279
+ * iteration after the turn finalizes.
93280
+ */
93281
+ runPostTurnTruncation() {
93282
+ try {
93283
+ const bossTrimmed = truncateOversizedToolResults(this.bossAgent.getMessages());
93284
+ let workerTrimmed = 0;
93285
+ for (const w of this.workers.values()) {
93286
+ workerTrimmed += truncateOversizedToolResults(w.getMessagesRef());
93287
+ }
93288
+ if (bossTrimmed > 0 || workerTrimmed > 0) {
93289
+ log2("INFO", "truncate_tool_results", "trimmed oversized results", {
93290
+ boss: bossTrimmed,
93291
+ workers: workerTrimmed
93292
+ });
93293
+ if (typeof globalThis.gc === "function") globalThis.gc();
93294
+ }
93295
+ } catch (err) {
93296
+ const message = err instanceof Error ? err.message : String(err);
93297
+ log2("ERROR", "truncate_tool_results", message);
93298
+ }
93299
+ }
93136
93300
  async persistNewMessages() {
93137
93301
  if (!this.sessionPath) return;
93138
93302
  const all = this.bossAgent.getMessages();
@@ -93348,6 +93512,7 @@ var GGBoss = class {
93348
93512
  bossStore.appendInfo(formatProviderError(message), "error");
93349
93513
  }
93350
93514
  bossStore.finishStreaming();
93515
+ this.runPostTurnTruncation();
93351
93516
  await this.persistNewMessages();
93352
93517
  if (event.kind === "worker_turn_complete" && finishedTaskId) {
93353
93518
  await this.maybeAutoChain(event.summary.project);
@@ -93729,4 +93894,4 @@ react/cjs/react-jsx-runtime.development.js:
93729
93894
  * LICENSE file in the root directory of this source tree.
93730
93895
  *)
93731
93896
  */
93732
- //# sourceMappingURL=chunk-KWWLOD25.js.map
93897
+ //# sourceMappingURL=chunk-FXGI4NWS.js.map